NSOperationQueue:一系列NSOperation的依赖VS(maxConcurrentOperationCount == 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)如果我换到op1
和op2
左右,程序实际上会做什么? (op2
应在op1
之后执行,但队列只能同时从操作中取出一个)
P.S.在我的应用程序中,我使用AFHTTPRequestOperation
。它的继承层次:
AFHTTPRequestOperation
- >AFURLConnectionOperation
- >NSOperation
所以我不能简单地采取其他的NSOperation
子类。
回答您的问题:
- 它的安全操作的这一特定序列与已与
maxConcurrentOperations = 1
给出的依赖关系结合起来。 - 如果颠倒的
op1
和op2
的依赖顺序的队列将运行op2
,op3
和op1
或op2
,op1
,op3
。
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); }];
我同意几乎所有的事情,但等待。 'NSBlockOperation'具有'executionBlocks'。我应该在添加检查单独块时取消吗? – Gargo 2014-11-18 19:29:35
显然是的,即使在块中,您也需要明确检查操作取消。您可以在将其添加到队列并查看会发生什么之前取消操作来自行尝试。 – 2014-11-18 20:53:26
如果包含块操作的队列被取消,那么它甚至不会启动。你只需要检查isCancelled如果在块内做一些像循环一样慢的事情。 – malhal 2017-01-09 01:31:38