我现在正在将一些代码转换为带有 async-await 和Task. 我想知道的一件事是可以在 Task 实例中使用 DispatchQueue ,例如
Task {
await someHeavyStuff()
DispatchQueue.main.async {
someUIThreadStuff()
}
}
Run Code Online (Sandbox Code Playgroud)
据我所知,Task 和 DispatchQueue 在处理异步事物方面几乎没有什么不同的机制,所以我担心使用两者可能会弄乱线程系统。
(我知道我可以MainActor.run {}在这种情况下使用)
Rob*_*Rob 15
你逃脱了DispatchQueue.main.async { \xe2\x80\xa6 },但你真的应该放弃这种模式。但是,如果您有一个大型复杂项目,正在慢慢过渡到 Swift 并发,并且还没有时间清理它,是的,您现在可以摆脱这个 GCD 调用。
但正确的解决方案是仅标记someUIThreadStuff为@MainActor并淘汰DispatchQueue.main.async { \xe2\x80\xa6 }. 这是一个微不足道的修复,就像MainActor.run { \xe2\x80\xa6 }。在向 Swift 并发过渡过程中可能要处理的所有事情中,这是最容易做的事情之一,并且摆脱 GCD API。
当您过渡到 Swift 并发时,必须特别小心的是使用锁和信号量或阻塞当前线程的地方。Swift 并发无法推理这些,而这些可能是问题的根源。但是,对主队列的延迟调度不太可能导致问题,尽管您当然应该尽早删除它。查看Swift 并发:幕后花絮,特别是有关运行时契约的讨论,以确保永远不会阻止前进。
\n当我查看您的代码片段时,我会更关心 to Task { \xe2\x80\xa6 }start someHeavyStuff。名称 \xe2\x80\x9cstartHeavyStuff\xe2\x80\x9d 表明计算成本较高,会阻塞当前线程。但Task { \xe2\x80\xa6 }用于在当前 actor 上启动异步任务,而不是用于在后台线程上运行 \xe2\x80\x9cheavy\xe2\x80\x9d 任务。现在,someHeavyStuff以某种方式从当前演员那里得到它,然后忽略这个警告。但要小心,不要假设它Task { \xe2\x80\xa6 }会表现得像DispatchQueue.global().async { \xe2\x80\xa6 },因为事实并非如此。
我建议观看 WWDC 2021 Swift 并发:更新示例应用程序。它介绍了重构遗留代码的非常实用的练习。
\n| 归档时间: |
|
| 查看次数: |
3726 次 |
| 最近记录: |