.collectSwift 的组合中的操作将在哪个线程上发出预期的线程?
具体来说,我在第二个前提条件中看到此代码崩溃,但在第一个前提条件中没有崩溃:
return Publishers.MergeMany(publishers)
.handleEvents(receiveOutput: { _ in
precondition(Thread.isMainThread) // <- This is fine
})
.collect()
.handleEvents(receiveOutput: { _ in
precondition(Thread.isMainThread) // <- Crash is here
})
Run Code Online (Sandbox Code Playgroud)
就好像该.collect操作正在选择一个不同的线程来使用,即使最终的发布者必须MergeMany在主线程上发出。我通过从 Firebase 上传的崩溃日志推断出此行为。谁能解释这种观察到的行为?
为了进行检查,请尝试使用dispatchPrecondition(condition: .onQueue(.main)). 这在 Swift 中相当于调用dispatch_assert_queue. 如果您阅读那里的文档,您将看到:
将dispatch_get_main_queue() 的结果传递给此函数可验证当前块是否已提交到主队列、或以它为目标的队列、或正在主线程上运行(在任何上下文中)。
请注意,它说“或正在主线程上运行”
Grand Central Dispatch 可以在非主线程的线程上执行以主队列为目标的队列上的代码。因此,即使代码在至少目前是“主”执行上下文的上下文中运行,显式比较当前线程与主线程的前提条件检查也可能无效。
如果您查看标头文档,dispatch_get_current_queue您会发现:
当在主线程上调用dispatch_get_current_queue()时,它可能会或可能不会返回与dispatch_get_main_queue()相同的值。比较两者并不是测试代码是否在主线程上执行的有效方法(请参阅dispatch_assert_queue()和dispatch_assert_queue_not())。
在您的情况下,我怀疑收集事件正在针对主队列的队列上运行,并且代码不在主线程上运行,但操作系统确保您的代码不与主线程并行运行,因此没有竞争条件的机会。
| 归档时间: |
|
| 查看次数: |
124 次 |
| 最近记录: |