ios - 为什么我们在主线程上使用异步
问题描述
在主线程以外的线程上更新 UI 是一个常见错误,可能导致错过 UI 更新、视觉缺陷、数据损坏和崩溃。
https://developer.apple.com/documentation/code_diagnostics/main_thread_checker
例子:
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
if let data = data {
DispatchQueue.main.async { // Correct
self.label.text = "\(data.count) bytes downloaded"
}
}
}
task.resume()
我的问题从这里开始 - 当我们说不.async
同时(或不平行)时,我对上述陈述感到困惑.main
。有人可以解释我的问题吗?
解决方案
DispatchQueue.main.async
意味着您在主队列中排队一个任务,而无需等待任务执行。主队列任务将自动在主线程上运行,由操作系统调度。
将每个人都DispatchQueue
视为工人。调用.async
会在 worker 的 TODO 列表下添加一个任务,不要等待 worker 完成任务。DispathQueue.main
是在主线程上工作的特定工作者。
哦,另一方面,.sync
将阻塞线程,直到任务块完成执行。您可以调用.sync
除主线程之外的任何线程,因为不能阻塞主线程。
这并不意味着您不能调用DispatchQueue.main.sync
. 您可以像在非主线程上调用任何自定义 dispathQueue.sync 一样调用 DispatchQueue.main.sync。
例如
DispatchQueue(label: "bgqueue", qos: .background).async
{
DispatchQueue.main.sync{}
}
没关系。
但
DispatchQueue.main.async{
DispatchQueue.main.sync{}
}
不是。
.sync
通常不是很有用。如果您希望在主队列任务之后发生某些事情,您只需将“某事”也排队到主队列中。如果没有必要,不值得阻塞线程。
话虽如此,使用 时要记住以下两条规则.sync
,无论哪个队列正在接收.sync
呼叫:
- 永远不要
.sync
从队列调用自身,这会导致死锁。 - 永远不要
.sync
从主队列调用,这会阻塞 UI 线程。
推荐阅读
- embedded-linux - SELinux init_daemon_domain(avahi_t,avahi_exec_t) 与 files_types(avahi_t)
- android - Android Kotlin - imageUrl 的绑定适配器 AK(android.widget.ImageView, java.lang.String) 已经存在
- node.js - 使用 Highland.js 将一个流与来自另一个流的数据进行水合
- javascript - 在 Javascript/knockout js 函数中传递对象丢失值
- javascript - React Router Link重新加载页面:与外部事件冲突
- flutter - Flutter:初始值未在表单中更新(FormBuilder)
- algorithm - 按字典顺序排序的堆栈排列
- swift - Swift 最终会有原生选择器吗?
- webrtc - WebRTC 移动摄像头不切换
- python - 在 Python 中,这个带有嵌套列表的列表是如何排序的?