1

例如,我有 3 个对象:

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)如果我交换op1and ,程序实际上会做op2什么?(op2应该在之后执行,op1但队列只能同时从操作中获取一个)

PS 在我的应用程序中,我使用AFHTTPRequestOperation. 它的继承层次结构:

AFHTTPRequestOperation-> AFURLConnectionOperation->NSOperation

所以我不能简单地采用NSOperation.

4

1 回答 1

1

要回答您的问题:

  1. 将这个特定的操作序列与您给出的依赖项结合起来是安全的maxConcurrentOperations = 1
  2. 如果反转 and 的依赖顺序,队列将运行op2,op3op1or op2, 。op1op3op1op2

您指定的依赖链没有什么棘手的,NSOperationQueue可以自动处理。op3如果您指定循环依赖项(例如,取决于op1),或者您有一个未添加到队列中的操作,因此您无法执行以满足依赖项,您只会真正遇到麻烦。

Apple对 NSOperationQueue 类参考中的取消有这样的说法:

取消操作会导致操作忽略它可能具有的任何依赖项。这种行为使队列可以尽快执行操作的 start 方法。反过来, 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];
    }
}

要让 aNSBlockOperation引用自己,您需要这样做,这有点恶心,但在NSOperation子类中看起来更好,因为您可以引用self.

__block NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"op1 cancelled=%d", op1.cancelled); }];
于 2014-11-16T20:12:49.600 回答