提问人:Duck 提问时间:10/26/2011 最后编辑:mfaaniDuck 更新时间:4/12/2019 访问量:145674
iPhone - Grand Central Dispatch 主线程
iPhone - Grand Central Dispatch main thread
问:
我一直在我的应用程序中成功地使用大中央调度,但我想知道使用这样的东西的真正优势是什么:
dispatch_async(dispatch_get_main_queue(), ^{ ... do stuff
甚至
dispatch_sync(dispatch_get_main_queue(), ^{ ... do stuff
我的意思是,在这两种情况下,您都在触发一个要在主线程上执行的块,正是应用程序运行的位置,这无助于减少负载。在第一种情况下,您无法控制块何时运行。我见过在你触发后半秒钟就被执行的案例。第二种情况,类似于
[self doStuff];
右?
我想知道你们怎么看。
答:
将块调度到主队列通常是从后台队列完成的,以表示某些后台处理已完成,例如
- (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
- 在后台队列上处理的数据块 - >信号主队列开始下一个块
- 后台队列上的传入网络数据 -> 表示主队列消息已到达
- 等等等等
至于为什么你可能想从主队列调度到主队列......好吧,你通常不会这样做,尽管可以想象,你可能会这样做来安排一些工作,以便在下次运行循环中完成。
评论
希望我正确理解了您的问题,因为您想知道dispatch_async和dispatch_sync之间的区别吗?
dispatch_async
将块异步调度到队列。这意味着它会将块发送到队列,而不是等待它返回,然后继续执行方法中的剩余代码。
dispatch_sync
将块同步调度到队列。这将阻止在块完成执行之前再执行方法中的剩余代码。
我主要使用后台队列来处理主队列的工作,并利用设备可能具有的任何额外内核。如果我需要更新 UI,然后到主线程。dispatch_async
dispatch_async
祝你好运
评论
将块从主线程分派到主队列可能很有用。它使主队列有机会处理其他已排队的块,这样您就不会简单地阻止其他所有内容的执行。
例如,您可以编写一个本质上是单线程的服务器,但该服务器仍可处理许多并发连接。只要队列中没有单个块花费太长时间,服务器就会保持对新请求的响应。
如果你的程序什么都不做,只是花了整个生命来响应事件,那么这可能是很自然的。您只需将事件处理程序设置为在主队列上运行,然后调用 dispatch_main(),您可能根本不需要担心线程安全。
它有用的一个地方是用于 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。
评论
Async 表示异步,您应该在大部分时间使用它。切勿在主线程上调用 sync,因为它会锁定您的 UI,直到任务完成。You Here 是 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
斯威夫特 3、4 和 5
在主线程上运行代码
DispatchQueue.main.async {
// Your code here
}
评论