iPhone - Grand Central Dispatch主线程

问题描述 投票:142回答:6

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

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

甚至

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

我的意思是,在这两种情况下,你都要触发一个块来在主线程上执行,确切地说应用程序在哪里运行,这无助于减少负载。在第一种情况下,当块运行时,您没有任何控制权。我已经看到在你开火后半秒执行块的情况。第二种情况,它类似于

[self doStuff];

对?

我想知道你们的想法是什么。

ios concurrency grand-central-dispatch dispatch-async
6个回答
293
投票

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

- (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
  • 在后台队列上处理的数据块 - >信号主队列以启动下一个块
  • 后台队列上的传入网络数据 - >消息已到达的信号主队列
  • 等等

至于为什么你可能想要从主队列调度到主队列......好吧,你通常不会想到你可能会在下一次运行循环时安排一些工作。


15
投票

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

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

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


11
投票

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

dispatch_async

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

dispatch_sync

将同步调度块到队列。这将阻止在块完成执行之前不再执行方法中的剩余代码。

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

祝好运


8
投票

一个有用的地方是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。


8
投票

斯威夫特3,4和5

在主线程上运行代码

DispatchQueue.main.async {
    // Your code here
}

1
投票

异步意味着异步,你应该在大多数时候使用它。您永远不应该在主线程上调用同步,因为它会锁定您的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

© www.soinside.com 2019 - 2024. All rights reserved.