gpt4 book ai didi

swift 并发: Why Task is not executed on other background thread

转载 作者:行者123 更新时间:2023-12-03 08:01:39 25 4
gpt4 key购买 nike

我正在尝试学习快速并发,但它带来了很多困惑。我知道 Task {} 是一个异步单元,它允许我们从同步上下文桥接异步函数调用。它类似于 DispatchQueue.Global() ,后者将在某个任意线程上执行该 block 。

override func viewDidLoad() {
super.viewDidLoad()

Task {
do {

let data = try await asychronousApiCall()
print(data)

} catch {
print("Request failed with error: \(error)")
}
}

for i in 1...30000 {
print("Thread \(Thread.current)")
}
}

我的 asychronousApiCall 函数如下

func asychronousApiCall() async throws -> Data {
print("starting with asychronousApiCall")
print("Thread \(Thread.current)")
let url = URL(string: "https://www.stackoverflow.com")!
// Use the async variant of URLSession to fetch data
// Code might suspend here
let (data, _) = try await URLSession.shared.data(from: url)

return data
}

当我尝试这个实现时。我总是看到在 for 循环 完成并且线程是 MainThread 后打印“starting with asychronousApiCall”。

像这样

Thread <_NSMainThread: 0x600000f10500>{number = 1, name = main}

最佳答案

你说:

I understood that a Task {} is an asynchronous unit and will allow us to bridge the async function call from a synchronous context.

是的。

您继续:

And it is similar to DispatchQueue.global() which in turn will execute the block on some arbitrary thread.

不,如果您从主要参与者调用它,它更类似于 DispatchQueue.main.async { ... }。作为documentation说,它“代表当前参与者异步执行给定的非抛出操作,作为新的顶级任务的一部分”[强调]。即,如果您当前是主要 Actor ,则任务也将代表主要 Actor 运行。

虽然专注于直接 GCD 到并发映射可能是错误的,但 Task.detached { … }DispatchQueue.global().async { … } 更具可比性.

您评论过:

Please scroll to figure 8 in last of the article. It has a normal task and Thread is print is some other thread.

figure 8图8

在该屏幕快照中,它们显示在挂起点之前(即,在 await 之前)它位于主线程上(这是有道理的,因为它代表同一个 Actor )。但他们也强调,在挂起点之后,它在另一个线程上(这可能看起来违反直觉,但这是挂起点之后可能发生的情况)。这是 Swift 并发中非常常见的行为,尽管可能有所不同。

FWIW,在上面的示例中,您只检查挂起点之前的线程,而不是之后。图 8 的主要信息是挂起点之后使用的线程可能与挂起点之前使用的线程不同。

如果您有兴趣了解有关其中一些实现细节的更多信息,我建议您观看 WWDC 2021 视频 Swift concurrency: Behind the scenes .


虽然查看Thread.current很有趣,但应该指出的是,Apple 正在试图让我们摆脱这种做法。例如,在 Swift 5.7 中,如果我们从异步上下文中查看 Thread.current,我们会收到警告:

Class property 'current' is unavailable from asynchronous contexts; Thread.current cannot be used from async contexts.; this is an error in Swift 6

Swift 并发的整体思想是,我们不再考虑线程,而是让 Swift 并发代表我们选择适当的线程(这巧妙地避免了代价高昂的上下文切换;有时会导致代码在其他线程上运行)超出我们的预期)。

关于 swift 并发: Why Task is not executed on other background thread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73896515/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com