NSOperationQueue何时开始其第一次操作?

Ste*_*her 11 cocoa cocoa-touch nsoperationqueue

我已经创建了一个测试项目,我正在测试我的假设,NSOperationNSOperationQueue在我的主项目中使用它们之前.

我的代码非常简单,所以我将在这里包含所有内容.这是在启用ARC的情况下使用命令行Foundation项目.

Operation.h

#import <Foundation/Foundation.h>

@interface Operation : NSOperation

@property (readwrite, strong) NSString *label;

- (id)initWithLabel: (NSString *)label;

@end
Run Code Online (Sandbox Code Playgroud)

Operation.m

#import "Operation.h"

@implementation Operation

- (void)main
{
    NSLog( @"Operation %@", _label);
}

- (id)initWithLabel: (NSString *)label
{
    if (( self = [super init] )) {
        _label = label;
    }
    return self;
}

@end
Run Code Online (Sandbox Code Playgroud)

的main.m

#import <Foundation/Foundation.h>
#import "Operation.h"

int main(int argc, const char * argv[])
{

    @autoreleasepool {

        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        queue.maxConcurrentOperationCount = 1;

        id create = [[Operation alloc] initWithLabel: @"create"];
        id update1 = [[Operation alloc] initWithLabel: @"update1"];
        id update2 = [[Operation alloc] initWithLabel: @"update2"];

        [update1 addDependency: create];
        [update2 addDependency: create];

        [queue addOperation: update1];
        [queue addOperation: create];
        [queue addOperation: update2];

        [queue waitUntilAllOperationsAreFinished];

    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我的输出如下:

2012-05-02 11:37:08.573 QueueTest[1574:1b03] Operation create
2012-05-02 11:37:08.584 QueueTest[1574:1903] Operation update2
2012-05-02 11:37:08.586 QueueTest[1574:1b03] Operation update1
Run Code Online (Sandbox Code Playgroud)

写完这个并尝试了几个组合之后,我发现当我重新排序这样的队列设置时:

    [queue addOperation: update1];
    [queue addOperation: create];
    [queue addOperation: update2];

    [update1 addDependency: create];
    [update2 addDependency: create];

    [queue waitUntilAllOperationsAreFinished];
Run Code Online (Sandbox Code Playgroud)

我得到了相同的输出:

2012-05-02 11:38:23.965 QueueTest[1591:1b03] Operation create
2012-05-02 11:38:23.975 QueueTest[1591:1b03] Operation update1
2012-05-02 11:38:23.978 QueueTest[1591:1903] Operation update2
Run Code Online (Sandbox Code Playgroud)

我应该注意到我在一些运行中发现update2在update1之前执行,但这种行为并不令人惊讶.NSOperationQueue当我没有问过它时,为什么要确定?

觉得奇怪的是,不知何故创造UPDATE1即使一切都添加到队列中添加依赖关系之前UPDATE2之前始终执行.

显然,这是一个愚蠢的事情,但它让我想知道:从我向队列添加操作到何时执行文档或以任何方式可预测之间的延迟?究竟何时NSOperationQueue开始处理添加的操作?

真的,最重要的是,究竟是什么NSOperationQueue等待什么,等待什么时候会以某种方式咬我,我无法防范?

Pet*_*sey 16

显然,这是一个愚蠢的事情,但它让我想知道:从我向队列添加操作到何时执行文档或以任何方式可预测之间的延迟?究竟NSOperationQueue何时开始处理添加的操作?

后:

  • 您将操作添加到队列,
  • 所有操作的依赖关系都已完成,并且
  • 队列没有更好的(在优先级方面).

对于没有不满足的依赖关系的操作,这可能意味着立即.

进一步的实验似乎表明,NSOperationQueue会在当前线程通过[queue waitUntilAllOperationsAreFinished],[NSThread sleepForTimeInterval:0.000001]或中断的线程产生控制权时立即开始运行操作.

这个假设是假的,原因有两个:

  1. 抢占式多任务处理,在每个版本的OS X(以及每个版本的iOS)上完成,意味着调度程序可以随时中断您的线程.你不需要控制失去控制.
  2. 每个当前OS X和iOS设备都具有多个核心,意味着操作可以addOperation:返回之前逐字开始(尽管这种极端情况不太可能仅仅是因为开销).更重要的是,其他操作可能能够在第一个操作时运行.

这两点,尤其是后者,也意味着"秩序"的问题几乎被简化为无意义.您在依赖关系树中安排的操作将按照该树的顺序启动,但否则根本没有顺序; 你应该假设它们之间没有依赖关系的操作将同时运行,而不是一个接一个地运行.

操作开始后,向其添加依赖项无效.由于这可以在将其添加到队列后立即发生,因此如果希望依赖项可靠地生效,则必须在将操作添加到队列之前向操作添加依赖项.