Swift从同步上下文调用主要参与者上的异步函数



我试图理解为什么下面的代码会抛出断言。我想做的是从调用站点调用主线程/主要参与者上的asyncFunc()。我不想用@MainActor修饰asyncFunc,因为我希望函数与线程无关。

func asyncFunc() async -> String? {
dispatchPrecondition(condition: .onQueue(.main))
return "abc"
}
func callSite() {
Task { @MainActor in
await asyncFunc()
}
}

我的理解是Task { @MainActor ...}将在MainActor/main线程上执行以下所有代码。

如提议中所述,swift中的当前参与者是可重入的:

与参与者隔离的函数是可重入的。当与参与者隔离的函数挂起时,可重入性允许在原始与参与者隔离函数恢复之前对参与者执行其他工作,我们称之为交织。再入消除了死锁的来源,即两个参与者相互依赖,可以通过不必要地阻止参与者的工作来提高整体性能,并为更好地调度(例如(更高优先级的任务提供了机会。

因此,asyncFunc不会在MainActor上运行,因为它会阻止参与者处理其他高优先级任务。要解决这个问题,您可以尝试以下两种方法:

  1. 使您的函数同步,以便它在MainActor上运行:
func syncFunc() -> String? {
dispatchPrecondition(condition: .onQueue(.main))
return "abc"
}
func callSite() {
Task { @MainActor in
syncFunc()
}
}
  1. 或者显式标记要在MainActor上运行的异步函数:
@MainActor
func asyncFunc() async -> String? {
dispatchPrecondition(condition: .onQueue(.main))
return "abc"
}
func callSite() {
Task {
await asyncFunc()
}
}

注意,这里也适用相同的重入规则,asyncFunc(即dispatchPrecondition(中的同步调用将在MainActor上执行,而asyncFunc中的任何异步调用都不会在MainActor上调用。

最新更新