1

比如我有3個對象:NSOperationQueue:一系列NSOperation的依賴VS(maxConcurrentOperationCount == 1)?

NSOperation *op1 = ...; 
NSOperation *op2 = ...; 
NSOperation *op3 = ...; 

[op3 addDependency:op2]; 
[op2 addDependency:op1]; 

NSOperationQueue *queue = ...; 
queue.maxConcurrentOperationCount = 1; 
[queue addOperations:@[op1, op2, op3] waitUntilFinished:NO]; 

我可以簡單地添加在正確的順序所有操作。但是,例如,如果op2被取消,那麼我也應該取消op3,在這種情況下我不能完全清除隊列。

我的問題:

1)它是安全的操作,如序列與maxConcurrentOperationCount == 1結合?

2)如果我換到op1op2左右,程序實際上會做什麼? (op2應在op1之後執行,但隊列只能同時從操作中取出一個)

P.S.在我的應用程序中,我使用AFHTTPRequestOperation。它的繼承層次:

AFHTTPRequestOperation - >AFURLConnectionOperation - >NSOperation

所以我不能簡單地採取其他的NSOperation子類。

回答

1

回答您的問題:

  1. 它的安全操作的這一特定序列與已與maxConcurrentOperations = 1給出的依賴關係結合起來。
  2. 如果顛倒的op1op2的依賴順序的隊列將運行op2op3op1op2op1op3

Theres在您指定的依賴鏈中沒有任何棘手的問題,而NSOperationQueue可以自動處理事情。如果指定循環依賴關係(例如op3取決於op1),或者您有未添加到隊列的操作,並且無法執行以滿足依賴關係,那麼只能真正遇到問題。

蘋果這在the NSOperationQueue class reference說關於取消:

取消的操作使操作忽略它可能有任何相關性。這種行爲使得隊列儘快執行操作的啓動方法成爲可能。 start方法反過來將操作移至完成狀態,以便將其從隊列中移除。

所有的NSOperation子類都應該通過首先檢查它是否被取消,然後立即完成操作而不執行任何操作來正確處理取消。如果沒有完成,那麼這是一個錯誤,即使它們已被取消,操作也可能執行。

(有趣的是,這也適用於NSBlockOperation,我沒有意識到,你明確需要在塊中檢查self.isCancelled)。

我在App Store上使用CodeRunner來嘗試這一切,並略微修改您的程序。它在下面轉載。

#import <Foundation/Foundation.h> 

int main(int argc, char *argv[]) { 
    @autoreleasepool { 
     NSOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"op1"); }]; 
     NSOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"op2"); }]; 
     NSOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"op3"); }]; 

     [op3 addDependency:op2]; 
     [op2 addDependency:op1]; 

     NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 
     queue.maxConcurrentOperationCount = 1; 

     [queue addOperations:@[op1, op2, op3] waitUntilFinished:YES]; 
    } 
} 

對於NSBlockOperation指本身,你需要做到這一點,這是一個有點噁心,但看起來在NSOperation子類,你可以參考self更好。

__block NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"op1 cancelled=%d", op1.cancelled); }]; 
+0

我同意幾乎所有的事情,但等待。 'NSBlockOperation'具有'executionBlocks'。我應該在添加檢查單獨塊時取消嗎? – Gargo 2014-11-18 19:29:35

+1

顯然是的,即使在塊中,您也需要明確檢查操作取消。您可以在將其添加到隊列並查看會發生什麼之前取消操作來自行嘗試。 – 2014-11-18 20:53:26

+0

如果包含塊操作的隊列被取消,那麼它甚至不會啓動。你只需要檢查isCancelled如果在塊內做一些像循環一樣慢的事情。 – malhal 2017-01-09 01:31:38

相關問題