NSOperationQueue阻止不相关的NSOperationQueue?

时间:2013-02-20 13:16:11

标签: iphone ios asynchronous concurrency nsoperation

我正在使用NSOperation和NSOperationQueue在背景中加载图像(用于2D游戏)。

为了理解NSOperations的行为,我尝试添加以下无关的NSOperationQueue / NSOperation(在开始任何图像加载之前我调用-startNewEndlessBackgroundTask方式):

static int stop = NO;
static int c = 1000;
-(void)takeTime {
    stop = NO;
    while (!stop) {
        for (int i = 0; i < 10000; i++) {
            c += 1;
        }
        c = c;
    }
}
-(void)stopBackgroundTask {
    stop = YES;
}
-(void)startNewEndlessBackgroundTask {
    //[self performSelectorInBackground:@selector(takeTime) withObject:nil];
    NSOperationQueue* queue = [[NSOperationQueue alloc] init];
    [queue addOperationWithBlock:^{
         [self takeTime];
    }];
}

这完全阻止了我在iPhone4上加载图像的其他NSOperationQueue。在iPhone4s上,它在2次调用startNewEndlessBackgroundTask后阻止我的图像加载。两者都在运行iOS 6。

我的应用程序的主循环未被阻止。

如果我改为使用performSelectorInBackground来调用takeTime,一切正常,没有阻塞,并且takeTime例程也在后台正常工作。

为什么会发生这种情况,当两个NSOperationQueue是完全分开的alloc-init'ted并且没有依赖关系?对我来说,以这种简单的方式使用NSOperationQueue和使用performSelectorInBackground之间应该没有什么区别,但我想有一些我误解的根本原因?

1 个答案:

答案 0 :(得分:0)

不确定细节,但这是我现在认为正在发生的事情的部分答案。

NSOperation在下面使用GCD(至少从OSX和iOS的最后几个版本开始)。 GCD中有一些全局优先级队列。

当优先级较高的队列中有任务时,优先级较低的队列中的任务甚至都没有启动(尽管同一全局优先级队列中的任务可以启动,因为尽管名称中有“队列”,但默认情况下的任务优先级队列可以并发)。

由于我没有指定任何线程优先级,我想我的-takeTime操作正在默认优先级队列上进行调度,我的映像加载操作正在默认的低优先级队列上进行调度。这可以解释为什么-takeTime操作阻止了我的图像加载。

这没有真正解释,为什么在iPhone 4s上需要两次-takeTime操作来阻止我的图像加载操作,因为低优先级队列中等待高优先级队列中的任务的任务未被提及为取决于CPU内核的数量 - 据我在文档中看到的那样。

Apple - Dispatch Queues: “除了获取默认并发队列之外,您还可以通过将DISPATCH_QUEUE_PRIORITY_HIGH和DISPATCH_QUEUE_PRIORITY_LOW常量传递给函数来获取具有高优先级和低优先级的队列,或者通过传递DISPATCH_QUEUE_PRIORITY_BACKGROUND常量来获取后台队列。期望,高优先级并发队列中的任务在默认队列和低优先级队列中的任务之前执行。同样,默认队列中的任务在低优先级队列中的任务之前执行。“