【问题标题】:swift async function is being run on the main thread in some cases when run from task在某些情况下,当从任务运行时,快速异步函数正在主线程上运行
【发布时间】:2021-12-13 15:33:44
【问题描述】:

在这种情况下,异步函数读取文件并返回解析后的内容。

在我看来,我想从主线程中加载内容,然后在完成后更新视图。

我在各个地方都使用过这种模式,并注意到在某些情况下异步调用在主线程上(通过调试),而在其他情况下它在 Thread 4 Queue : com.apple.root.user-initiated-qos.cooperative (concurrent) 线程上

例如:

struct MyView: View {
  @State var data = "some data"
  var body: some View {
    Button("refresh") {
    // when the button is pressed refresh it
            Task {
                await refresh()
            }
        }.task {
    // when the view appears
            await refresh()
        }
     Text("the data is \(data)") // write the data which was refreshed async
   }


  }
  func refresh() async {
        do {
            let res = try await anotherAyncFunction()
            data = res // this is presumably wrong and off the main thread - obviously might not be correct but leave here for debug as well
        } catch {
            print("got error \(error)")
        }
    }

我使用类似的模式创建了几个不同的视图(.task 块调用 async 函数)

在某些情况下,函数会长时间运行(从磁盘读取),并且这发生在主线程上

【问题讨论】:

标签: swift swiftui swift5.5 swift-concurrency


【解决方案1】:

Task { 更改为Task.detached {

来自Swift Language Guide

要创建在当前参与者上运行的非结构化任务,请调用 Task.init(priority:operation:) 初始化程序。要创建一个不属于当前参与者的非结构化任务(更具体地称为分离任务),请调用 Task.detached(priority:operation:) 类方法。

当您调用Task.init 时,异步代码在当前参与者上运行,在此上下文中,该参与者是主要参与者。这会导致阻塞主线程。

通过调用Task.detached,您允许异步工作发生在主线程之外。

【讨论】:

  • 不行,我的Task被分离了,但它在主线程上。
【解决方案2】:

使用 Swift 结构化并发,在后台线程上运行代码,使用分离任务或(更好)演员。

【讨论】:

    猜你喜欢
    • 2016-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-19
    相关资源
    最近更新 更多