146

我一直在成功地使用我的应用程序中的大型中央调度,但我想知道使用这样的东西的真正优势是什么:

dispatch_async(dispatch_get_main_queue(), ^{ ... do stuff

甚至

dispatch_sync(dispatch_get_main_queue(), ^{ ... do stuff

我的意思是,在这两种情况下,您都会触发一个要在主线程上执行的块,这正是应用程序运行的位置,这无助于减少负载。在第一种情况下,您无法控制块何时运行。我见过在你触发它们半秒后执行块的情况。第二种情况,类似

[self doStuff];

正确的?

我想知道你们怎么看。

4

6 回答 6

296

将块分派到主队列通常是从后台队列完成的,以表明某些后台处理已完成,例如

- (void)doCalculation
{
    //you can use any string instead "com.mycompany.myqueue"
    dispatch_queue_t backgroundQueue = dispatch_queue_create("com.mycompany.myqueue", 0);

    dispatch_async(backgroundQueue, ^{
        int result = <some really long calculation that takes seconds to complete>;

        dispatch_async(dispatch_get_main_queue(), ^{
            [self updateMyUIWithResult:result];
        });    
    });
}

在这种情况下,我们正在后台队列上进行冗长的计算,并且需要在计算完成后更新我们的 UI。更新 UI 通常必须从主队列完成,因此我们使用第二个嵌套的 dispatch_async 向主队列“发信号”。

可能还有其他示例,您可能希望将其分派回主队列,但通常以这种方式完成,即嵌套在分派到后台队列的块中。

  • 后台处理完成 -> 更新 UI
  • 在后台队列上处理的数据块 -> 向主队列发出信号以开始下一个块
  • 后台队列上的传入网络数据-> 通知主队列消息已到达
  • 等等等等

至于为什么你可能想主队列分派到主队列......好吧,你通常不会,尽管可以想象你可能会这样做来安排一些工作在下一次运行循环周围做。

于 2011-10-26T16:06:42.420 回答
17

从主线程向主队列分派块可能很有用。它使主队列有机会处理已排队的其他块,这样您就不会简单地阻止其他所有内容执行。

例如,您可以编写一个本质上是单线程的服务器,它仍然可以处理许多并发连接。只要队列中没有单个块花费太长时间,服务器就会保持对新请求的响应。

如果您的程序只在其整个生命周期中响应事件什么都不做,那么这可能是很自然的。您只需将事件处理程序设置为在主队列上运行,然后调用 dispatch_main(),您可能根本不需要担心线程安全。

于 2012-04-11T19:51:46.773 回答
11

希望我能正确理解您的问题,因为您想知道 dispatch_async 和 dispatch_sync 之间的区别?

dispatch_async

将块异步分派到队列。这意味着它会将块发送到队列,而不是等待它返回,然后继续执行方法中的剩余代码。

dispatch_sync

将块同步分派到队列中。这将阻止方法中剩余代码的任何更多执行,直到块完成执行。

我主要使用dispatch_async后台队列来完成主队列的工作,并利用设备可能拥有的任何额外内核。dispatch_async如果我需要更新 UI,然后到主线程。

祝你好运

于 2011-10-26T16:24:42.803 回答
9

它有用的一个地方是 UI 活动,例如在冗长的操作之前设置一个微调器:

- (void) handleDoSomethingButton{

    [mySpinner startAnimating];

    (do something lengthy)
    [mySpinner stopAnimating];
}

将不起作用,因为您在冗长的事情中阻塞了主线程并且没有让 UIKit 实际启动微调器。

- (void) handleDoSomethingButton{
     [mySpinner startAnimating];

     dispatch_async (dispatch_get_main_queue(), ^{
          (do something lengthy)
          [mySpinner stopAnimating];
    });
}

将控制权返回给运行循环,它将安排 UI 更新,启动微调器,然后将下一件事情从调度队列中取出,这是您的实际处理。处理完成后,将调用动画停止,然后返回到运行循环,然后 UI 会随着停止而更新。

于 2014-07-10T02:48:11.743 回答
8

斯威夫特 3、4 和 5

在主线程上运行代码

DispatchQueue.main.async {
    // Your code here
}
于 2018-02-16T12:23:56.173 回答
1

Async 意味着异步,您应该在大多数情况下使用它。你不应该在主线程上调用同步,因为它会锁定你的 UI,直到任务完成。你在这里是在 Swift 中执行此操作的更好方法:

runThisInMainThread { () -> Void in
    // Run your code like this:
    self.doStuff()
}

func runThisInMainThread(block: dispatch_block_t) {
    dispatch_async(dispatch_get_main_queue(), block)
}

它作为标准功能包含在我的仓库中,请查看:https ://github.com/goktugyil/EZSwiftExtensions

于 2015-12-06T03:44:53.980 回答