通过DispatchGroup与DispatchQueue访问主队列 [英] Accessing main queue via DispatchGroup vs. DispatchQueue

查看:21
本文介绍了通过DispatchGroup与DispatchQueue访问主队列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在后台线程上运行的类中使用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 { }

为什么这些不同?

推荐答案

当您调用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访问主队列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆