- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个管理数组的单例。这个单例可以从多个线程访问,所以它有自己的内部 DispatchQueue
来管理跨线程的读/写访问。为简单起见,我们将其称为串行队列。
有时单例将从数组中读取数据并更新 UI。我该如何处理?
不知道我的内部调度队列是哪个线程,对吧?这只是一个我不用担心的实现细节?在大多数情况下,这似乎没问题,但在这个特定函数中,我需要确保它使用主线程。
是否可以按照以下方式做某事:
myDispatchQueue.sync { // Synchronize with internal queue to ensure no writes/reads happen at the same time
DispatchQueue.main.async { // Ensure that it's executed on the main thread
for item in internalArray {
// Pretend internalArray is an array of strings
someLabel.text = item
}
}
}
所以我的问题是:
myDispatchQueue.sync(forceMainThread: true) { ... }
?DispatchQueue.main.async { ... }
,并且我从主线程调用该函数,我能否确定我的内部调度队列将在与所谓的相同(主)线程?或者这也是一个“实现细节”,但它也可以在后台线程上调用?基本上我感到困惑的是,线程似乎是您不应该为队列担心的实现细节,但是当您确实需要担心时,偶尔会发生什么?
简单示例代码:
class LabelUpdater {
static let shared = LabelUpdater()
var strings: [String] = []
private let dispatchQueue: dispatchQueue
private init {
dispatchQueue = DispatchQueue(label: "com.sample.me.LabelUpdaterQueue")
super.init()
}
func add(string: String) {
dispatchQueue.sync {
strings.append(string)
}
}
// Assume for sake of example that `labels` is always same array length as `strings`
func updateLabels(_ labels: [UILabel]) {
// Execute in the queue so that no read/write can occur at the same time.
dispatchQueue.sync {
// How do I know this will be on the main thread? Can I ensure it?
for (index, label) in labels.enumerated() {
label.text = strings[index]
}
}
}
}
最佳答案
是的,您可以将对一个队列的调度嵌套在对另一个队列的调度中。我们经常这样做。
但是要非常小心。仅使用来自同步队列的分派(dispatch)将异步分派(dispatch)包装到主队列是不够的。您的第一个示例不是线程安全的。您从主线程访问的数组可能会从您的同步队列中发生变化:
这是一个 race condition因为您可能有多个线程(您的同步队列的线程和主线程)与同一个集合交互。与其将分派(dispatch)到主队列的 block 直接与 objects
交互,不如复制它的副本,这就是在分派(dispatch)到主队列中引用的内容。
例如,您可能想要执行以下操作:
func process(completion: @escaping (String) -> Void) {
syncQueue.sync {
let result = ... // note, this runs on thread associated with `syncQueue` ...
DispatchQueue.main.async {
completion(result) // ... but this runs on the main thread
}
}
}
这确保主队列不与此类的任何内部属性交互,而只是将在此闭包中创建的 result
传递给 syncQueue
。
请注意,所有这些都与它是一个单例无关。但是既然你提出了这个话题,我建议不要对模型数据使用单例。它适用于接收器、无状态 Controller 等,但通常不建议用于模型数据。
我绝对不鼓励直接从单例启动 UI 控件更新的做法。我倾向于提供这些方法完成处理程序闭包,并让调用者负责生成的 UI 更新。当然,如果您想将闭包分派(dispatch)到主队列(为方便起见,在许多第三方 API 中很常见),那很好。但是单例不应该进入并更新 UI 控件本身。
我假设您所做的所有这些只是为了说明目的,但我向可能不会理解这些担忧的 future 读者添加了这个警告词。
关于ios - 如何确保我的 DispatchQueue 专门在主线程上执行一些代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59615860/
我是一名优秀的程序员,十分优秀!