为什么我们在主线程上使用异步

Ami*_*mit 2 grand-central-dispatch ios swift

在主线程以外的线程上更新 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()
Run Code Online (Sandbox Code Playgroud)

我的问题从这里开始 - 当我们说.async意味着与.main. 有人可以解释我的问题吗?

Ric*_* Mo 6

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{} 
} 
Run Code Online (Sandbox Code Playgroud)

没问题。

DispatchQueue.main.async{ 
    DispatchQueue.main.sync{} 
} 
Run Code Online (Sandbox Code Playgroud)

不是。

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

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

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