【发布时间】:2020-04-24 05:14:54
【问题描述】:
我有一个管理数组的单例。这个单例可以从多个线程访问,因此它有自己的内部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]
}
}
}
}
【问题讨论】:
-
发布您的线程安全单例,以便我们查看。
-
要回答您的问题,当您需要在主线程上执行某个后台任务的某些部分时,嵌套调度队列是强制性的。您的示例代码的概念是标准做法。我将如何实际实现它是另一回事。
-
别再担心线程了,想想队列吧?
-
我什至不知道“是否保证在主线程上也调用函数 B 的调度队列”是什么意思。如果您在某个队列上调用一个方法,那么显然会在该队列上调用它。
-
“保证从主线程执行“Hello world”的打印“什么??保证从调度队列 test.test.test2 中执行。
标签: ios swift multithreading cocoa-touch grand-central-dispatch