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陷入僵局。