Shi*_*ava 7 multithreading asynchronous ios swift 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)
}
}
Run Code Online (Sandbox Code Playgroud)
例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)
}
}
Run Code Online (Sandbox Code Playgroud)
据我所知,
Quest1: - 那么为什么我的应用程序在后台线程(即main.async)执行任务时崩溃,而不是调用主线程来更新UI.
Quest2: - main.async和global().async有什么区别.
yoA*_*ex5 11
大中华区
Thread -> GCD -> Operation + OperationQueue(life cycle, dependencies between different queues, cancel)
Run Code Online (Sandbox Code Playgroud)
Grand Central Dispatch GCD libdispatchDispatchQueue以 FIFO 顺序对调度队列进行操作
DispatchQueue.<queue>.<sync/async>意味着<sync/async>在<queue>
队列
通常,当我们谈论时,concurrent我们谈论的是队列。线程数取决于操作系统条件。没有run loop工作线程。
concurrent具有不同优先级的队列组(主线程、高、默认、低、后台),您使用qos QoSClass(服务质量)(priority GlobalQueuePriority已弃用)在任务中传递这些队列:
userInteractive- 主线程 - 最优先。它可用于非常快速的计算,并立即反映在 UI 上。例如动画计算userInitiated- 高优先级队列 - 与 UI 相关。长达数秒。例如加载用于在 UI 上显示的数据default - 默认优先级队列utility - 低优先级队列 - 最多几分钟,例如处理图像等大数据,处理...background - 后台优先队列 - 应用程序在后台运行时长达几个小时,如同步数据。
GCD 支持:
global queue - 在整个 iOS 操作系统之间共享private queuemain-全局队列,用于处理 UI的主线程上的串行队列
DispatchQueue.main
Run Code Online (Sandbox Code Playgroud)
global()-全局队列,并发队列。
DispatchQueue.global()
DispatchQueue.global(qos: .background)
Run Code Online (Sandbox Code Playgroud)
自定义队列: -私人队列,serial或concurrent自定义队列
DispatchQueue(label: "serialQueue") // without attributes
DispatchQueue(label: "concurrentQueue", attributes: .concurrent)
Run Code Online (Sandbox Code Playgroud)
同步/异步
sync - 阻塞当前线程并等待它在指定队列上完成
async - 不要阻塞当前线程并将执行代码块发送到指定的队列
常见错误:死锁
如果您DispatchQueue.main.sync在main线程上调用- 应用程序将被冻结,因为DispatchQueue.main.sync当分派块完成时调用立即开始等待(分派块未启动)
一些注意事项:
DispatchWorkItem- 延迟/取消/优先处理内部Queue或DispatchGroupDispatchGroup如果您打算使用单个回调执行多个异步任务,即使在不同的队列上。所有这些任务都应该分组。DispatchGroup包含线程安全计数器,当它等于 0 时notify被调用//create group
let group = DispatchGroup()
//case 1
DispatchQueue.<queue>.async(group: group) //
//case 2 - manual
group.enter() //<- +1
DispatchQueue.global().async {
//logic
group.leave() //<- -1
}
//notification
group.notify(queue: <callback_queue>) {
//logic
}
Run Code Online (Sandbox Code Playgroud)
Barrier内标志并发队列的同步/异步任务担保不存在race condition(多个线程同时进行写操作)。最好的地方是自定义队列,因为它不会阻塞任何其他全局任务:customQueue.async(flags: .barrier) {
//logic
someProperty = someValue
}
Run Code Online (Sandbox Code Playgroud)
thread safe操作可以通过Barrier在共享变量的并发队列中达到:
barrier【线程安全单例】
【Sync vs Async】
【iOS同步】
Shi*_*ava 10
简单来说,我得出的结论是 -
DispatchQueue.main.async
- 这意味着使用后台线程(没有阻止UI)在主队列中执行任务,当任务完成时自动更新到UI,因为它已经在主队列中.
DispatchQueue.global().async以及global().sync
它意味着使用后台线程在全局队列中执行任务,当任务完成时,比global().sync use将工作从globalQueue带到mainQueue,后者更新到UI.
我的应用程序崩溃的原因
我试图通过使用(main.sync)将完成的任务带到MainQueue,但它已经在MainQueue上,因为我没有切换Queue,这创建了DeadLock(MainQueue等待自己),导致我的应用程序崩溃
在第一种情况下,您运行代码main然后main.sync在主线程上使用.本质上,你试图告诉main队列等待自己 - 这显然是无稽之谈,因此它会导致崩溃.
在第二种情况下,您在后台线程上运行代码,然后使用main.sync等待main线程可以运行提供的块main.sync.
一般来说,我会使用async而不是sync所有的时间,除非sync是必要的 - 并且始终将一个线程(DispatchQueue)与另一个线程同步,从不使用相同的线程.
| 归档时间: |
|
| 查看次数: |
5082 次 |
| 最近记录: |