GCD在主线程中执行任务

Egi*_*gil 228 objective-c grand-central-dispatch

我有一个可能来自任何线程的回调.当我得到这个回调,然后我想在主线程上执行某个任务.

我是否需要检查我是否已经在主线程上 - 或者是否因为没有执行此检查而遭受任何惩罚?请调用下面的代码?

dispatch_async(dispatch_get_main_queue(), ^{
   // do work here
});
Run Code Online (Sandbox Code Playgroud)

小智 143

不,您不需要检查您是否已经在主线程上.通过将块分派给主队列,您只是在主线程上调度要串行执行的块,这在运行相应的运行循环时发生.

如果您已经在主线程上,则行为是相同的:块被调度,并在运行主线程的运行循环时执行.

  • 但是,您需要检查是否使用dispatch_sync.否则你会陷入僵局. (6认同)
  • 问题是是否存在"不执行此检查的惩罚"......我认为在没有必要时使用异步调度会有性能损失,还是微不足道? (3认同)

Bra*_*son 99

对于上面描述的异步调度情况,您不需要检查是否在主线程上.正如Bavarious所说,这将简单地排队等候在主线程上运行.

但是,如果您尝试使用a执行上述操作dispatch_sync()并且您的回调位于主线程上,那么您的应用程序将在此时死锁.我在这里的答案中对此进行了描述,因为在移动某些代码时,这种行为让我感到惊讶-performSelectorOnMainThread:.正如我在那里提到的,我创建了一个辅助函数:

void runOnMainQueueWithoutDeadlocking(void (^block)(void))
{
    if ([NSThread isMainThread])
    {
        block();
    }
    else
    {
        dispatch_sync(dispatch_get_main_queue(), block);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你所在的方法当前不在主线程上,它将在主线程上同步运行一个块,如果是,则只执行块内联.您可以使用以下语法来使用它:

runOnMainQueueWithoutDeadlocking(^{
    //Do stuff
});
Run Code Online (Sandbox Code Playgroud)

  • 为什么不将其称为“runOnMainQueueSync”?事实上,它可能会死锁,但不会死锁,这是我不希望在我的代码中出现的情况。谢谢,一如既往的+1。 (2认同)
  • @Yar - 我刚刚给它这个名字,所以我很清楚为什么我不只是在主队列上同步触发块而不是使用这个辅助函数.这更像是对自己的提醒. (2认同)
  • 使用此功能仍有可能死锁.主队列同步>其他队列同步>主队列将死锁. (2认同)
  • @hfossli - 是的,它不会处理所有情况。在我的使用中,我总是从后台串行队列上的异步调度或主线程上的内联代码调用。我想知道在您描述的情况下 `dispatch_set_specific()` 是否会有所帮助:http://stackoverflow.com/a/12806754/19679。 (2认同)

Mic*_*nen 50

正如其他提到的答案,主线程中的di​​spatch_async很好.

但是,根据您的使用情况,有一个副作用,您可能会认为是一个缺点:由于块是在队列上调度的,因此在控制返回到运行循环之前它不会执行,这会产生延迟效果你的块的执行.

例如,

NSLog(@"before dispatch async");
dispatch_async(dispatch_get_main_queue(), ^{
    NSLog(@"inside dispatch async block main thread from main thread");
});
NSLog(@"after dispatch async");
Run Code Online (Sandbox Code Playgroud)

将打印出来:

before dispatch async
after dispatch async
inside dispatch async block main thread from main thread
Run Code Online (Sandbox Code Playgroud)

出于这个原因,如果您希望块在外部NSLog之间执行,dispatch_async将无法帮助您.


归档时间:

查看次数:

113952 次

最近记录:

10 年,1 月 前