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

时间:2017-10-13 14:18:33

标签: ios swift multithreading asynchronous swift3

示例A: - 这会导致App Crash。

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&是否有任何区别全球()。异步。

4 个答案:

答案 0 :(得分:7)

简单来说,我得出结论 -

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

DispatchQueue.main.async

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

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

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

我的应用崩溃的原因

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

答案 1 :(得分:5)

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

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

一般情况下,我会一直使用async而不是sync,除非需要sync - 并始终将一个帖子(DispatchQueue)同步一个从来没有相同的。

答案 2 :(得分:4)

Grand Central Dispatch GCD对具有FIFO顺序的调度队列DispatchQueue进行操作

DispatchQueue.<queue>.<sync/async>意味着在<sync/async>

上运行<queue>任务

队列

main-主线程上的串行队列,该线程用于处理UI

DispatchQueue.main

global()-系统共享的并发队列。 global()方法在任务中使用qos QoSClass传递优先级(不推荐使用priority GlobalQueuePriority):backgrounddefault,{ {1}},unspecifieduserInitiateduserInteractive

utility

自定义队列:-DispatchQueue.global() DispatchQueue.global(qos: .background) serial自定义队列

concurrent

同步/异步

DispatchQueue(label: "serialQueue") DispatchQueue(label: "concurrentQueue", attributes: .concurrent) -阻止当前线程,并等待何时在指定队列上完成

sync-不要阻塞当前线程,并且不要将执行代码块发送到指定的队列

常见错误:

如果您在async线程上调用DispatchQueue.main.sync-应用程序将被冻结,因为调用main会在调度块完成(调度块未启动)后立即开始等待。< / p>

[Sync vs Async]

答案 3 :(得分:3)

你混淆了术语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陷入僵局。