我正在使用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];
}];
}这会完全阻止我的另一个NSOperationQueue在iPhone4上加载图像。在iPhone4s上,它会在2次调用startNewEndlessBackgroundTask后阻止我的图像加载。两者都在运行iOS 6。
我的应用程序的主循环没有被阻塞。
如果我使用performSelectorInBackground来调用takeTime,一切都可以正常工作,没有阻塞,takeTime例程也可以在后台正常工作。
当两个NSOperationQueue完全独立且没有依赖关系时,为什么会发生这种情况?对我来说,以这种简单的方式使用NSOperationQueue和使用performSelectorInBackground之间应该没有区别,但我猜我误解了一些基本的东西?
发布于 2013-03-11 21:48:54
不确定细节,但这是我现在认为正在发生的事情的部分答案。
NSOperation在底层使用GCD (至少从上几个OSX和iOS版本开始是这样)。GCD中存在某些全局优先级队列。
当较高优先级队列中有任务时,较低优先级队列中的任务甚至不会启动(尽管同一全局优先级队列中的任务可以启动,因为尽管它们的名称中有" queue“,但默认优先级队列中的任务可以是并发的)。
因为我没有指定任何线程优先级,所以我假设我的-takeTime操作是在默认优先级队列上调度的,而我的图像加载操作是在默认低优先级队列上调度的。这就解释了为什么-takeTime操作阻塞了我的图像加载。
这并没有真正解释为什么需要两次-takeTime操作才能阻止我在iPhone 4s上的图像加载操作,因为低优先级队列中的任务等待高优先级队列中的任务并没有提到取决于CPU核心的数量-就我在文档中看到的那样。
Apple - Dispatch Queues:“除了获取默认的并发队列外,您还可以通过将DISPATCH_QUEUE_PRIORITY_HIGH和DISPATCH_QUEUE_PRIORITY_LOW常量传递给函数来获取高优先级和低优先级的队列,或者通过传递DISPATCH_QUEUE_PRIORITY_BACKGROUND常量来获取后台队列。正如您可能预期的那样,高优先级并发队列中的任务在默认和低优先级队列中的任务之前执行。类似地,默认队列中的任务在低优先级队列中的任务之前执行。”
https://stackoverflow.com/questions/14980787
复制相似问题