7
{
    dispatch_queue_t myQueue = dispatch_queue_create("com.mycompany.myqueue", 0);

    dispatch_sync(myQueue, ^{

        //Do EXTREME PROCESSING!!!
        for (int i = 0; i< 100; i++) {
            [NSThread sleepForTimeInterval:.05];
            NSLog(@"%i", i);
        }

        dispatch_sync(dispatch_get_main_queue(), ^{
            [self updateLabelWhenBackgroundDone];
        });
    });
}

我在这里陷入僵局。根据苹果文档

“dispatch_sync”:“将块提交到调度队列以进行同步执行。与 dispatch_async 不同,此函数在块完成之前不会返回。调用此函数并以当前队列为目标会导致死锁。”。

但是,我先做外层dispatch_syncmyQueue然后再做内层ditpatch_sync的另一个队列是`main_queue。

无法找出死锁的原因。任何意见/帮助在这里表示赞赏。

4

3 回答 3

12

如果你像这样 dispatch_sync 到 myQueue 并且调用发生在主线程上,那么 dispatch_sync 将在可能的情况下执行该块,而不是像 dispatch_async 这样的新工作线程。您不能保证为您的队列获得单独的工作线程。

然后该块在主线程上运行,直到它遇到您的第二个 dispatch_sync 调用,该调用恰好针对主队列。无法为该队列提供服务,因为它上面已经有一个块在运行,这就是你最终陷入死锁的地方。

如果这是您的问题,即第一个 dispatch_sync 确实来自主线程,那么您应该切换到 dispatch_async。您不想用长时间运行的“EXTREME PROCESSING”操作阻塞主线程。

于 2013-08-18T08:38:28.053 回答
7

你打dispatch_sync了两次电话。第一次暂停主线程等待你的块完成。然后该块通过第二次调用挂起后台线程,该调用试图推回主线程(主线程将永远不会处理其队列中的块,因为它已挂起)。两个线程现在都在等待对方。

至少有一个调用需要是dispatch_async.

于 2013-08-18T08:36:08.553 回答
2

我有类似的问题,这些解决方案都没有奏效。我问过比我聪明的人。

我的问题是我正在生成一个调度异步工作块,然后显示一个进度窗口。通过回调到主线程

dispatch_sync(dispatch_get_main_queue(), ^{})

和异步调用一样失败。

解释是由于模式窗口,主线程不再处于“公共模式”。我用这个替换了对主线程的调用....

CFRunLoopPerformBlock(([[NSRunLoop mainRunLoop] getCFRunLoop]), (__bridge CFStringRef)NSModalPanelRunLoopMode, ^{
        //Update UI thread.

    });
于 2014-08-19T23:46:18.310 回答