关于nsoperationqueue,我们遇到了一个简单的问题,下面是一个简单的操作逻辑:
self.queue = [[NSOperationQueue alloc] init];
NSOperation *operationA = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"- Running operation A");
[NSThread sleepForTimeInterval:1.2];
NSLog(@"- Done operation A");
}];
NSOperation *operationB = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"- Running operation B");
[NSThread sleepForTimeInterval:2];
NSLog(@"- Done operation B");
}];
[operationA setCompletionBlock:^{
NSLog(@"-- Completion Block A");
}];
[operationB setCompletionBlock:^{
NSLog(@"-- Completion Block B");
}];
[operationB addDependency:operationA];
[self.queue addOperations:@[operationA, operationB] waitUntilFinished:NO];
这是最后的结果
2015-12-21 14:59:57.463 SampleProject[18046:310901] - Running operation A
2015-12-21 14:59:58.664 SampleProject[18046:310901] - Done operation A
2015-12-21 14:59:58.664 SampleProject[18046:310900] - Running operation B
2015-12-21 14:59:58.664 SampleProject[18046:310904] -- Completion Block A
2015-12-21 15:00:00.736 SampleProject[18046:310900] - Done operation B
2015-12-21 15:00:00.736 SampleProject[18046:310904] -- Completion Block B
如我们所见,操作b在操作a的completionblock之前执行。在我们的实际应用中,我们有很多操作a,只有一个操作b依赖于所有操作a。但是我们的问题是,操作b在调用最后一个操作a的完成块之前启动,这通常会向操作b提供信息。
在操作a的所有完成块之后,我如何使操作b执行?
最佳答案
正如您在测试完成块中发现的,它们不是“队列的一部分”,而是运行在操作队列之外(和另一个线程上)。因此A操作系统的运行将与操作B同时运行。
我建议您重构代码以删除所有完成块。
你说你正在使用completionblocks将信息从操作a传递到操作b,有两种选择:给b引用所有的a(不是弱的),这样当b运行时,它可以从所有的a中选择结果。或者如果由于某种原因,在b运行之前保持所有的a都在附近是不可行的,然后将CompletionBlock重新创建为另一个nsoperation:
NSOperation *operationA = [NSBlockOperation blockOperationWithBlock:^{
// do stuff
}];
NSOperation *operationATail = [NSBlockOperation blockOperationWithBlock:^{
// do completionBlock stuff
}];
[operationATail addDependency:operationA];
[operationB addDependency:operationATail];
[self.queue addOperations:@[operationA, operationATail, operationB] waitUntilFinished:NO];