我希望能够“真正地”序列化异步方法,例如:

  • 发出网络请求
  • 显示 UIAlertView

  • 这通常是一项棘手的业务,大多数串行队列示例在 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 方法也需要被覆盖,但为了简洁起见,您可能省略了它。

    10-08 14:42