首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >等待使用主线程还是协作线程池?

等待使用主线程还是协作线程池?
EN

Stack Overflow用户
提问于 2022-10-05 10:02:56
回答 1查看 141关注 0票数 0

我知道“等待”并不直接生成一个新线程,而是告诉函数挂起,这样系统就可以利用线程进行其他工作。但是,当涉及到系统将如何/哪个线程继续执行等待的任务/工作时,还有点不清楚。

我正在Xcode 14上测试这个,在这里我有3个提取版本。下面是我的观察

  • ViewModel.fetch1:在主线程上运行
  • ViewModel.fetch2:在协作线程池上运行
  • ContentView.fetch:在主线程上运行
代码语言:javascript
复制
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.fetchViewModel.fetch1方法,Task继承参与者上下文是可以理解的,因为我在使用main的SwiftUI body中创建了非结构化Task

对于ViewModel.fetch2方法,我将其标记为async,而且Swift决定使用协作线程池而不是“继承”主参与者上下文?

EN

回答 1

Stack Overflow用户

发布于 2022-10-06 06:19:04

你问:

等待使用主线程还是协作线程池?

await不指定线程。它只是在代码中引入了一个暂停点。一切都取决于你等待的是什么。

问题是Task { … }“运行给定的.作为新的顶级任务的一部分,代表当前参与者异步操作。“

如果你想让它脱离主演员,你应该使用Task.detached { … }

正如文档 for Data(contentsOf:)所说:

不要使用此同步初始化程序请求基于网络的URL。对于基于网络的URL,这种方法可以在一个缓慢的网络上阻塞当前线程几十秒,导致用户体验差,在iOS中,可能会导致应用程序被终止。

因此,除了从本地文件系统读取小文件之外,我将避免使用Data(contentsOf:)。相反,使用URLSession

代码语言:javascript
复制
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) ?? ""
}

这完全避免了需要担心您从哪个角色运行它的问题。它还提供取消功能和许多其他好处。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73958785

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档