2

我正在使用 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 完全分开分配初始化并且没有依赖关系时,为什么会发生这种情况?对我来说,以这种简单的方式使用 NSOperationQueue 和使用 performSelectorInBackground 之间应该没有区别,但我想我误解了一些基本的东西?

4

1 回答 1

0

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

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

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

由于我没有指定任何线程优先级,我想我的 -takeTime 操作被安排在默认优先级队列上,而我的图像加载操作被安排在默认的低优先级队列上。这可以解释为什么 -takeTime 操作会阻止我的图像加载。

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

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

于 2013-03-11T13:48:54.117 回答