我知道“等待”并不直接生成一个新线程,而是告诉函数挂起,这样系统就可以利用线程进行其他工作。但是,当涉及到系统将如何/哪个线程继续执行等待的任务/工作时,还有点不清楚。
我正在Xcode 14上测试这个,在这里我有3个提取版本。下面是我的观察
class ViewModel: ObservableObject {
@Published var string = ""
func fetch1() {
let url = URL(string: "https://google.com")!
let data = try! Data(contentsOf: url)
self.string = String(data: data, encoding: .utf8) ?? ""
}
func fetch2() async {
let url = URL(string: "https://google.com")!
let data = try! Data(contentsOf: url)
self.string = String(data: data, encoding: .utf8) ?? ""
}
}
struct ContentView: View {
@State var string = ""
@StateObject var vm = ViewModel()
var body: some View {
VStack {
Button {
Task {
await vm.fetch1()
}
Task {
await vm.fetch2()
}
Task {
await fetch()
}
} label: {
Text("Fetch")
}
Text(string)
Text(vm.string)
}
}
private func fetch() async {
let url = URL(string: "https://google.com")!
let data = try! Data(contentsOf: url)
self.string = String(data: data, encoding: .utf8) ?? ""
}
}我知道使用新的异步/等待并发模型,考虑线程是不明智的,但在这里,我试图确保它不会在主线程上运行繁重的工作。
对于在主线程上执行的ContentView.fetch和ViewModel.fetch1方法,Task继承参与者上下文是可以理解的,因为我在使用main的SwiftUI body中创建了非结构化Task。
对于ViewModel.fetch2方法,我将其标记为async,而且Swift决定使用协作线程池而不是“继承”主参与者上下文?
发布于 2022-10-06 06:19:04
你问:
等待使用主线程还是协作线程池?
await不指定线程。它只是在代码中引入了一个暂停点。一切都取决于你等待的是什么。
问题是Task { … }“运行给定的.作为新的顶级任务的一部分,代表当前参与者异步操作。“
如果你想让它脱离主演员,你应该使用Task.detached { … }。
正如文档 for Data(contentsOf:)所说:
不要使用此同步初始化程序请求基于网络的URL。对于基于网络的URL,这种方法可以在一个缓慢的网络上阻塞当前线程几十秒,导致用户体验差,在iOS中,可能会导致应用程序被终止。
因此,除了从本地文件系统读取小文件之外,我将避免使用Data(contentsOf:)。相反,使用URLSession
func fetch3() async throws -> String {
let url = URL(string: "https://google.com")!
let (data, _) = try await URLSession.shared.data(from: url)
return String(data: data, encoding: .utf8) ?? ""
}这完全避免了需要担心您从哪个角色运行它的问题。它还提供取消功能和许多其他好处。
https://stackoverflow.com/questions/73958785
复制相似问题