NSOperationQueue 阻塞不相关的 NSOperationQueue?

Posted

技术标签:

【中文标题】NSOperationQueue 阻塞不相关的 NSOperationQueue?【英文标题】:NSOperationQueue blocking unrelated NSOperationQueue? 【发布时间】:2013-02-05 12:13:42 【问题描述】:

我正在使用 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 之间应该没有区别,但我想我误解了一些基本的东西?

【问题讨论】:

【参考方案1】:

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

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

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

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

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

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

【讨论】:

以上是关于NSOperationQueue 阻塞不相关的 NSOperationQueue?的主要内容,如果未能解决你的问题,请参考以下文章

多线程编程NSOperationQueue

GCD的同步异步串行并行NSOperation和NSOperationQueue一级用dispatch_once实现单例

iOS开发-91GCD的同步异步串行并行NSOperation和NSOperationQueue一级用dispatch_once实现单例(转载)

NSOperationQueue mainQueue 不更新 UICollectionViewCell

iPhone 上的 Objective-C - NSOperationQueue 和 NSInvocationOperation 的使用

iOS多线程总结——NSOperation与NSOperationQueue的使用