Swift3 GCD中的main.async vs main.sync()vs global()。async

示例A: – 这导致应用程序崩溃。

DispatchQueue.main.async { let url = URL(string: imageUrl) do { let data = try Data(contentsOf: url!) DispatchQueue.main.sync { self.imageIcon.image = UIImage(data: data) } } 

例B: – 但事实并非如此

 DispatchQueue.global().async { let url = URL(string: imageUrl) do { let data = try Data(contentsOf: url!) DispatchQueue.main.sync { self.imageIcon.image = UIImage(data: data) } } 

据我所知,

  • x.sync意味着在主线程/ UI线程中执行操作而x.async意味着在后台线程中执行操作。
  • 全局意味着执行具有并发队列的东西,即并行任务

Quest1: – 那么为什么我的应用程序在后台线程(即main.async)执行任务时崩溃,而不是调用主线程来更新UI。

Quest2: – main.async和global()。async有什么区别。

在第一种情况下,您在main上运行代码,然后在主线程上使用main.sync 。 本质上,你试图告诉main队列等待自己 – 这显然是无稽之谈,因此它会导致崩溃。

在第二种情况下,您在后台线程上运行代码,然后使用main.sync等待main线程可以运行main.sync提供的块。

一般情况下,我会一直使用async而不是sync ,除非需要sync – 并且始终将一个线程( DispatchQueue )与另一个线程同步,从不使用相同的线程。

简单来说,我得出的结论是 –

  • 队列 – 有3种类型的队列,即1个主队列,4个全局队列和任意数量的自定义队列。
  • 线程 – 一个是主线程和系统提供给我们的其他后台线程。

DispatchQueue.main.async

– 这意味着使用后台线程(没有阻止UI)在主队列中执行任务,当任务完成时自动更新到UI,因为它已经在主队列中。

DispatchQueue.global()。async以及global()。sync

它意味着使用后台线程在全局队列中执行任务,当任务完成时,比global()。sync use将工作从globalQueue带到更新到UI的mainQueue

我的应用程序崩溃的原因

我试图通过使用(main.sync)将完成的任务带到MainQueue,但它已经在MainQueue上,因为我没有切换队列,这创建了DeadLock (MainQueue等待自己),导致我的应用程序崩溃

你混淆了术语sync / async和main / global。

同步 – 同步运行某个任务(即可以是主/全局/任何其他线程的线程将等待任务完成)

异步 – 异步运行某些任务(即可以是主/全局/任何其他线程的线程将任务推送到队列并继续执行块外的下一步。它不会等待)

现在让我们在你的代码中逐个崩溃:
让我们为我们的线程添加一些名称,以便我们理解:
1)ThreadA – 遇到你的调度语句(这也可以是主线程,但出于解释目的我感觉更好)
2)ThreadB – 在提交某个任务时创建的全局线程。
3)ThreadMain – 主线程

例A:
DispatchQueue.main.async – ThreadA来执行此语句并将您的块放在ThreadMain上并继续(因为它的异步)到块后的下一步。

现在让我们谈谈ThreadMain,它将从这里做些什么。 由于ThreadMain得到一个块(由ThreadA提交),它开始逐步执​​行,然后突然看到’DispatchQueue.main.sync’并将内部块提交到相同的TheradMain队列并保持onnnnn waitingggggg(因为它的同步)。 所以你真的让ThreadMain陷入僵局。