gmo*_*eda 4 concurrency swift swiftui
SwiftUI 有这个 .task(priority:_:)视图修饰符。它运行异步代码。默认优先级是userInitiated。没有提及它在哪个线程上运行。
仅通过测试似乎在后台线程上运行,但是:假设始终在非主线程中运行是否安全?
我不确定您如何得出这不在主线程上的结论,但是当我在调试器上运行它时,它在主队列上:
\n\n这是有道理的,因为body与主要演员隔离,我希望它task也代表当前演员(主要演员)运行。(如果你需要从当前演员那里得到一些东西,你通常会使用分离任务。不过,您只需要对缓慢的同步工作单元执行此操作。)
底线是,SwiftUI.task视图修饰符body与主要参与者隔离。(FWIW,我也通过多种方式凭经验验证了这一点。)
简而言之,如果您确实需要确保某些内容远离主要参与者(例如,在.task视图修改器内运行缓慢且同步的内容),请确保将其放在单独的参与者上、独立任务中或某种等效模式中。
其他一些观察结果:
\n顺便说一句,我们不再关注 Swift 并发中的线程。它可能会产生误导性的结果。Swift 并发使我们脱离了线程级推理。将来,Swift 6 将删除许多我们用来以编程方式查询的 APIThread信息的 API。最重要的是,不要再担心线程并专注于参与者隔离。
如果您确实想了解有关 Swift 并发线程模型的更多信息,请参阅 WWDC 2021 视频Swift 并发:幕后花絮。它并不直接触及.task视图修饰符问题,但它将帮助您理解为什么我们不再像以前那样关注线程。
就我个人而言,在我的.task视图修饰符中,我通常只是调用一些async方法,在这种情况下,视图修饰符使用的参与者.task在很大程度上变得无关紧要(因为我们只是await那个调用,它暂停了当前参与者的执行,将其释放以去做其他的东西)。
同样,回到 GCD 世界,我们浪费了大量的精力来担心我们是否从正确的队列中调用了某些特定的方法(如果我们搞砸了,就要处理运行时错误)。但在 Swift 并发中,我们将被调用的函数隔离到适当的参与者,现在如果我们没有正确调用它,我们会收到编译时警告(例如,Sendable当我们使用 \xe2\x80\x9c 严格并发检查\xe2 时双重检查类型) \x80\x9d 构建设置 \xe2\x80\x9cComplete\xe2\x80\x9d,忽略包含所需的await跨角色边界时所需的内容等)。
在评论中,您提到您正在 \xe2\x80\x9c 检查线程 \xe2\x80\xa6 内async任务修饰符 \xe2\x80\x9d 中的函数 [调用] 内的线程 \xe2\x80\xa6。
是的,在 Swift 5.7 中实现的SE-0338告诉我们,非隔离async函数 \xe2\x80\x9c 不能在任何 actor\xe2\x80\x99s 执行器 \xe2\x80\x9d 上运行。因此,除非它是一个以某种方式明确与主要参与者隔离的函数,否则它不会在主要参与者上运行。
| 归档时间: |
|
| 查看次数: |
649 次 |
| 最近记录: |