在Task里面使用DispatchQueue可以吗?
Is it ok to use DispatchQueue inside Task?
我现在正在使用 async-await 和 Task
将我的一些代码转换为并发代码。我想知道的一件事是可以在
等任务实例中使用 DispatchQueue
Task {
await someHeavyStuff()
DispatchQueue.main.async {
someUIThreadStuff()
}
}
据我所知,Task 和 DispatchQueue 在处理异步事物方面几乎没有什么不同的机制,所以我担心同时使用两者会弄乱线程系统。
(我知道在这种情况下我可以使用 MainActor.run {}
)
你逃脱了 DispatchQueue.main.async { … }
,但你真的应该放弃这个模式。但是如果你有一个大而复杂的项目,你正在慢慢过渡到 Swift 并发,并且还没有时间清理它,是的,你现在可以不用这个 GCD 调用。
但正确的解决方案是将 someUIThreadStuff
标记为 @MainActor
并停用 DispatchQueue.main.async { … }
。这是一个微不足道的修复,MainActor.run { … }
也是如此。在过渡到 Swift 并发的过程中,您可能要处理的所有事情中,这是最简单的事情之一,只需正确地做,并摆脱 GCD API.
在过渡到 Swift 并发时必须特别小心的地方是使用锁和信号量的地方,或者阻塞当前线程的地方。 Swift 并发性无法解释这些,而这些可能是问题的根源。但是对主队列的延迟调度不太可能导致问题,尽管您当然应该在方便的时候尽早将其删除。请参阅 Swift concurrency: Behind the scenes,特别是有关永远不会阻止前进进程的运行时契约的讨论。
当我查看您的代码片段时,我会更关注 Task { … }
以开始 someHeavyStuff
。 “startHeavyStuff”这个名字暗示了一些计算量大的东西,阻塞了当前线程。但是 Task { … }
用于在当前当前 actor 上启动异步任务 , 不适用于后台线程上的 运行 “繁重”任务。现在,someHeavyStuff
正在以某种方式从当前演员那里得到它,然后忽略这个警告。但是请注意,您不要假设 Task { … }
会像 DispatchQueue.global().async { … }
那样工作,因为它不会。
我建议观看 WWDC 2021 Swift concurrency: Update a sample app。它介绍了重构遗留代码的非常实用的练习。
我现在正在使用 async-await 和 Task
将我的一些代码转换为并发代码。我想知道的一件事是可以在
Task {
await someHeavyStuff()
DispatchQueue.main.async {
someUIThreadStuff()
}
}
据我所知,Task 和 DispatchQueue 在处理异步事物方面几乎没有什么不同的机制,所以我担心同时使用两者会弄乱线程系统。
(我知道在这种情况下我可以使用 MainActor.run {}
)
你逃脱了 DispatchQueue.main.async { … }
,但你真的应该放弃这个模式。但是如果你有一个大而复杂的项目,你正在慢慢过渡到 Swift 并发,并且还没有时间清理它,是的,你现在可以不用这个 GCD 调用。
但正确的解决方案是将 someUIThreadStuff
标记为 @MainActor
并停用 DispatchQueue.main.async { … }
。这是一个微不足道的修复,MainActor.run { … }
也是如此。在过渡到 Swift 并发的过程中,您可能要处理的所有事情中,这是最简单的事情之一,只需正确地做,并摆脱 GCD API.
在过渡到 Swift 并发时必须特别小心的地方是使用锁和信号量的地方,或者阻塞当前线程的地方。 Swift 并发性无法解释这些,而这些可能是问题的根源。但是对主队列的延迟调度不太可能导致问题,尽管您当然应该在方便的时候尽早将其删除。请参阅 Swift concurrency: Behind the scenes,特别是有关永远不会阻止前进进程的运行时契约的讨论。
当我查看您的代码片段时,我会更关注 Task { … }
以开始 someHeavyStuff
。 “startHeavyStuff”这个名字暗示了一些计算量大的东西,阻塞了当前线程。但是 Task { … }
用于在当前当前 actor 上启动异步任务 , 不适用于后台线程上的 运行 “繁重”任务。现在,someHeavyStuff
正在以某种方式从当前演员那里得到它,然后忽略这个警告。但是请注意,您不要假设 Task { … }
会像 DispatchQueue.global().async { … }
那样工作,因为它不会。
我建议观看 WWDC 2021 Swift concurrency: Update a sample app。它介绍了重构遗留代码的非常实用的练习。