我希望能够“真正地”序列化异步方法,例如:
这通常是一项棘手的业务,大多数串行队列示例在 NSBlockOperation 的块中显示“ sleep ”。这不起作用,因为只有在回调发生时操作才完成。
我已经通过继承 NSOperation 来实现这一点,这是实现中最有趣的部分:
+ (MYOperation *)operationWithBlock:(CompleteBlock)block
{
MYOperation *operation = [[MYOperation alloc] init];
operation.block = block;
return operation;
}
- (void)start
{
[self willChangeValueForKey:@"isExecuting"];
self.executing = YES;
[self didChangeValueForKey:@"isExecuting"];
if (self.block) {
self.block(self);
}
}
- (void)finish
{
[self willChangeValueForKey:@"isExecuting"];
[self willChangeValueForKey:@"isFinished"];
self.executing = NO;
self.finished = YES;
[self didChangeValueForKey:@"isExecuting"];
[self didChangeValueForKey:@"isFinished"];
}
- (BOOL)isFinished
{
return self.finished;
}
- (BOOL) isExecuting
{
return self.executing;
}
这很好用,这是一个演示......
NSOperationQueue *q = [[NSOperationQueue alloc] init];
q.maxConcurrentOperationCount = 1;
dispatch_queue_t queue = dispatch_queue_create("1", NULL);
dispatch_queue_t queue2 = dispatch_queue_create("2", NULL);
MYOperation *op = [MYOperation operationWithBlock:^(MYOperation *o) {
NSLog(@"1...");
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"1");
[o finish]; // this signals we're done
});
}];
MYOperation *op2 = [MYOperation operationWithBlock:^(MYOperation *o) {
NSLog(@"2...");
dispatch_async(queue2, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"2");
[o finish]; // this signals we're done
});
}];
[q addOperations:@[op, op2] waitUntilFinished:YES];
[NSThread sleepForTimeInterval:5];
请注意,我还使用了 sleep ,但确保它们在后台线程中执行以模拟网络调用。日志内容如下
1...
1
2...
2
这是所需要的。这种方法有什么问题?有什么我应该注意的警告吗?
最佳答案
乍一看这行得通,但有些部分缺少“适当的” NSOperation 子类。
您不应对“取消”状态,您应该在开始时检查 isCancelled
,如果返回 YES ( "responding to the cancel command" ),则不要开始isConcurrent
方法也需要被覆盖,但为了简洁起见,您可能省略了它。