dispatch_sync无法与主队列

时间:2015-07-26 21:21:34

标签: objective-c grand-central-dispatch

请考虑以下代码:

dispatch_queue_t myQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_group_t myGroup = dispatch_group_create();

    dispatch_group_async(myGroup, myQueue, ^{
        NSLog(@"First block of code");
    });

    dispatch_group_async(myGroup, myQueue, ^{
        NSLog(@"Second block of code");
    });

    dispatch_group_async(myGroup, myQueue, ^{


        dispatch_sync(dispatch_get_main_queue(), ^{ //problem here

            dispatch_time_t myTime = dispatch_time(DISPATCH_TIME_NOW, 10ull * NSEC_PER_SEC);

            dispatch_after(myTime, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                NSLog(@"Third block of code work");

            });
        });

    });

    dispatch_group_wait(myGroup, DISPATCH_TIME_FOREVER);
    NSLog(@" All done ?");

问题出在dispatch_sync(dispatch_get_main_queue(), ^{ 当我发出dispatch_async(dispatch_get_main_queue(),^ {时,它可以正常工作。进行同步的点是阻塞主线程10秒,模拟“努力工作”。但不幸的是,它不起作用。我想知道为什么?

我想要的是:dispatch_sync 阻止主线程仅10秒,然后继续执行。

事实上发生了什么:从任何进一步的执行中调度同步块整个应用程序。

2 个答案:

答案 0 :(得分:2)

如果该代码在主事件循环上运行,则dispatch_group_wait()将阻止主队列。这可以防止主队列上任何块的同步执行,并导致死锁。

您可以通过暂停调试器来验证这一点。您可能会在调用等待时看到主线程/队列被阻塞,并且在dispatch_sync上阻塞了辅助线程/队列。

答案 1 :(得分:1)

您的代码可能在主队列上运行。它在后台调度三个块,然后等待,直到所有三个块都完成运行。由于这是在主队列上完成的,因此其他块将仅在之后开始在主队列上运行,即在排队的所有三个异步块完成之后。

现在这三个块中的第三个用同步调用调用主线程。这意味着它是向主队列添加一个块,然后它等待直到块开始执行,然后它等待直到块完成执行,然后dispatch_sync调用返回到它的调用者。

好吧,调度到主线程的块无法开始执行,因为主线程忙于等待三个异步块完成,其中一个块无法完成,因为它正在等待调度到主线程的块线程开始执行,它不能因为等等永远。实际上,在同步块中尝试执行的操作实际上并不重要,因为该块永远不会开始执行。