通过 DispatchGroup 与 DispatchQueue 访问主队列
Posted
技术标签:
【中文标题】通过 DispatchGroup 与 DispatchQueue 访问主队列【英文标题】:Accessing main queue via DispatchGroup vs. DispatchQueue 【发布时间】:2018-03-14 20:20:07 【问题描述】:我在后台线程上运行的类中使用 DispatchGroup。偶尔需要更新UI,所以调用如下代码:
dispatchGroup.notify(queue: .main)
self.delegate?.moveTo(sender: self, location: location)
self.delegate?.updateLabel(sender: self, item: self.currentItem)
不幸的是,什么也没发生。但是,如果我通过DispatchQueue.main.async
调用相同的代码,如下所示:
DispatchQueue.main.async
self.delegate?.moveTo(sender: self, location: location)
self.delegate?.updateLabel(sender: self, item: self.currentItem)
...委托调用成功。我的印象是dispatchGroup.notify(queue: .main)
相当于DispatchQueue.main.async
。
为什么这些不一样?
【问题讨论】:
【参考方案1】:在您调用notify(queue:)
时,您的dispatchGroup
是否为空(即没有块正在运行)?如果没有,正如documentation 所说dispatchGroup.notify(queue:)
当一组先前提交的块对象完成时,安排要提交到队列的工作项。
这意味着只有在最后一次 leave()
调用之后,当组变为空时,才会执行您的闭包。当然,enter()
s 和 leave()
s 必须平衡。
考虑以下示例:
let group = DispatchGroup()
group.enter()
someLongRunningTask()
// completion callback
group.leave()
group.enter()
anotherLongRunningTask()
// completion callback
group.leave()
group.notify(queue: .main)
print("all set")
在此示例中,all set
将仅在使用 group.leave()
执行的两个回调之后打印。
另一方面,DispatchQueue.main.async()
会立即将块提交到目标队列,但它不一定会在此之后立即开始 - 例如,可能会运行带有 .barrier
标志的 async
块。
更新:使用DispatchQueue
实现上述示例(希望它能让事情变得清晰):
let group = DispatchGroup()
group.enter()
someLongRunningTask()
// completion callback
group.leave()
group.enter()
anotherLongRunningTask()
// completion callback
group.leave()
group.wait() // waits synchronously for the submitted work to complete
DispatchQueue.main.async
print("all set")
【讨论】:
谢谢你这么详细的解释!这让我远离了。以上是关于通过 DispatchGroup 与 DispatchQueue 访问主队列的主要内容,如果未能解决你的问题,请参考以下文章
Swift 伪原子并发同步代码引起 DispatchGroup.leave() 方法不平衡调用导致 App 崩溃的解决
下载 Firebase 存储数据时,DispatchGroup 未正确执行