示例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)
}
}
据我所知,
Quest1: - 那么当我在后台线程中执行任务时,为什么我的应用程序崩溃了,即main.async,而不是调用主线程来更新UI。
Quest2: - main.async&是否有任何区别全球()。异步。
答案 0 :(得分:7)
简单来说,我得出结论 -
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
):background
,default
,{ {1}},unspecified
,userInitiated
,userInteractive
utility
自定义队列:-DispatchQueue.global()
DispatchQueue.global(qos: .background)
或serial
自定义队列
concurrent
同步/异步
DispatchQueue(label: "serialQueue")
DispatchQueue(label: "concurrentQueue", attributes: .concurrent)
-阻止当前线程,并等待何时在指定队列上完成
sync
-不要阻塞当前线程,并且不要将执行代码块发送到指定的队列
常见错误:
如果您在async
线程上调用DispatchQueue.main.sync
-应用程序将被冻结,因为调用main
会在调度块完成(调度块未启动)后立即开始等待。< / p>
答案 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陷入僵局。