2013-05-01 59 views
0

在我的應用程序中,我在後臺運行服務器。我正在使用NSOperation這樣做。 (我用GCD之前,但我需要能夠阻止它,所以我切換到NSOperation,但我仍然無法弄清楚如何)強制停止NSOperation或GCD?

所以基本上,我NSOperation子類看起來是這樣的:

- (void)main { 
    server_main(var1, var2); 
} 

由於這是一個服務器,server_main函數基本上不返回。我也無法控制該功能的實施。

偶爾,用戶會更改服務器的設置。發生這種情況時,我想停止然後重新啓動服務器。如果我理解正確,我需要在NSOperation子類中執行類似if (self.isCancelled)的操作,但由於它會卡在server_main函數中,所以我懷疑它實際上會起作用。

那麼我該如何停止服務器?

非常感謝!

回答

2

要做到這一點正確地看到Responding to Cancellation Events併發編程指南,這表示在:

雖然NSOperation類提供爲客戶取消操作,確認取消事件是需要自願的方式。如果一項行動徹底終止,可能無法收回已分配的資源。因此,預計操作對象將檢查取消事件,並在操作中間發生時正常退出。

要支持操作對象中的取消操作,您只需定期從自定義代碼中調用對象的isCancelled方法,並在返回YES時立即返回。

這是說的長篇大論方式,我真的覺得你需要能夠改變server_main,以便它可以:

  • 檢查isCancelled定期或

  • 有它提供一個回調/進度委託方法塊,這樣你就可以自己做到這一點,並且可以調用一些額外的函數/方法來取消server_main,讓它進入關鍵的清理過程。

如果你剛開始殺死進程(如果你甚至可以),你肯定會泄漏資源或留下server_main處於不一致的狀態。

我知道這不是您要找的答案,但這是取消操作的方式。抱歉。

+0

是的,我想......我知道這一點,但問題是我不能修改'server_main'出於某種原因。否則,我會完全做到這一點。 – aforaudrey 2013-05-01 13:07:17

+0

@iBlue - 對不起。這是一個阻力,但'server_main'實際上需要提供這兩種技術之一才能被取消。 (感嘆。)'server_main'是你可以用允許取消的東西來替換的東西嗎? (例如,某些框架可以作爲庫添加,或者可以將其源代碼編譯爲項目的一部分;如果您有源代碼,則可以編輯它)或者您堅持使用它? – Rob 2013-05-01 13:17:10

+0

是的,可悲的是我堅持它,因爲它是...「<雖然感謝。 – aforaudrey 2013-05-01 17:41:41

0

您可以使用NSOperationQueue的

- (void)setSuspended:(BOOL)suspend 

方法?在添加新操作之前,請檢查隊列是否使用isSuspended掛起?

編輯:這裏參數暫停 如果是YES,則該隊列停止調度排隊的操作來執行。如果否,則隊列再次開始調度操作。 討論 該方法暫停或恢復執行操作。暫停隊列可防止該隊列啓動其他操作。換句話說,在隊列恢復之前,阻止隊列中(或稍後添加到隊列中)並且尚未執行的操作啓動。暫停隊列不會停止正在運行的操作。

只有當它們完成執行時,才從隊列中刪除操作。但是,爲了完成執行,必須首先開始操作。由於暫停隊列不會啓動任何新操作,因此它不會刪除當前正在排隊並且未執行的任何操作(包括取消的操作)。

希望它可以幫助你。

+0

所以當我暫停一個隊列時,它會停止包含的操作,不管是什麼?但是,手術是否僅僅暫停,不停止?我需要停下來,開始一個新的副本......謝謝! – aforaudrey 2013-05-01 12:17:36

+0

似乎它不強制停止運行操作.. – aforaudrey 2013-05-01 12:26:27

+0

我已經更新了我的答案。檢查這個。 – 2013-05-01 12:37:29

0

你可以試試這個代碼:

@interface Canceller 
{ 
    BOOL _shouldCancel; 
} 
- (void)setShouldCancel:(BOOL)shouldCancel; 
- (BOOL)shouldCancel; 
@end 

@implementation Canceller 
- (void)setShouldCancel:(BOOL)shouldCancel { 
    _shouldCancel = shouldCancel; 
} 
- (BOOL)shouldCancel { 
    return _shouldCancel; 
} 
@end 

static void test(int a){ 
    static Canceller * canceller = nil; 

    if(q){ 
     [canceller setShouldCancel:YES]; 
     [canceller release]; 
     dispatch_suspend(q); 
     dispatch_release(q); 
     q=nil; 
    } 
    canceller = [[Canceller alloc] init]; 
    q=dispatch_get_global_queue(0,0); 
    dispatch_async(q,^ { 
     while(![canceller shouldCancel]){NSLog(@"query %d",a);sleep(2);} 
    }); 

} 

希望它能幫助。

+1

嘿謝謝你的回答。但是除非你明白代碼(我認爲是來自另一個SO帖子)的情況,我認爲它不適用於我的情況。如果你認爲否則,任何闡述是讚賞。 – aforaudrey 2013-05-01 12:40:11

+0

是否在操作隊列中添加NSOperation?如果你正在添加一個操作隊列,那麼你可以調用一個方法[queue cancelalloperations]; – 2013-05-01 12:44:46

+0

這並沒有明顯的幫助,因爲它們是相同的東西 – aforaudrey 2013-05-01 13:09:39