首页 > 解决方案 > 为什么我们在主线程上使用异步

问题描述

在主线程以外的线程上更新 UI 是一个常见错误,可能导致错过 UI 更新、视觉缺陷、数据损坏和崩溃。

https://developer.apple.com/documentation/code_diagnostics/main_thread_checker

例子:

let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
   if let data = data {
      DispatchQueue.main.async { // Correct
         self.label.text = "\(data.count) bytes downloaded"
      }
   }
}
task.resume()

我的问题从这里开始 - 当我们说不.async同时(或不平行)时,我对上述陈述感到困惑.main。有人可以解释我的问题吗?

标签: iosswiftgrand-central-dispatch

解决方案


DispatchQueue.main.async意味着您在主队列中排队一个任务,而无需等待任务执行。主队列任务将自动在主线程上运行,由操作系统调度。

将每个人都DispatchQueue视为工人。调用.async会在 worker 的 TODO 列表下添加一个任务,不要等待 worker 完成任务。DispathQueue.main是在主线程上工作的特定工作者。

哦,另一方面,.sync将阻塞线程,直到任务块完成执行。您可以调用.sync除主线程之外的任何线程,因为不能阻塞主线程。

这并不意味着您不能调用DispatchQueue.main.sync. 您可以像在非主线程上调用任何自定义 dispathQueue.sync 一样调用 DispatchQueue.main.sync。

例如

DispatchQueue(label: "bgqueue", qos: .background).async
{ 
    DispatchQueue.main.sync{} 
} 

没关系。

DispatchQueue.main.async{ 
    DispatchQueue.main.sync{} 
} 

不是。

.sync通常不是很有用。如果您希望在主队列任务之后发生某些事情,您只需将“某事”也排队到主队列中。如果没有必要,不值得阻塞线程。

话虽如此,使用 时要记住以下两条规则.sync,无论哪个队列正在接收.sync呼叫:

  1. 永远不要.sync从队列调用自身,这会导致死锁。
  2. 永远不要.sync从主队列调用,这会阻塞 UI 线程。

推荐阅读