You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在@MainActor类中让async函数在后台线程执行?

如何在后台线程运行@MainActor类中的耗时同步CPU密集型async函数?

我有一个标注@MainActor的类,其中包含一个async函数,这个函数执行耗时的同步CPU密集型操作:

@MainActor
class MyClass {
    // ...

    func getFoo() async -> Foo {
        let foo = // ... 一些耗时的同步CPU密集型操作 ...
        return foo
    }

    // ...
}

我想让这个函数在后台线程运行以避免阻塞主线程,见过两种实现方案,但不确定哪种正确(或是否都正确),因为两种方案都有反对观点。

两种常见实现方案

1. Task.detached方案

func getFoo() async -> Foo {
    await Task.detached {
        let foo = // ... 一些耗时的同步CPU密集型操作 ...
        return foo
    }.value
}

2. Continuation + GCD方案

func getFoo() async -> Foo {
    await withCheckedContinuation { continuation in
        DispatchQueue.global().async {
            let foo = // ... 一些耗时的同步CPU密集型操作 ...
            continuation.resume(returning: foo)
        }
    }
}

反对Task.detached方案的观点

无论是否在主actor中,都不应在并发上下文运行长期耗时的阻塞操作。Swift并发是协作式模型,即并发上下文中的函数应定期挂起以释放线程控制权,让运行时能在该线程上调度其他任务。

回想一下,Swift语言让我们能维护线程始终可向前推进的运行时契约。基于此契约,我们构建了协作式线程池作为Swift的默认执行器。采用Swift并发时,需确保代码维持该契约,以让协作式线程池最优运行。

根据以上观点,耗时同步操作不应在Swift并发中执行,否则会阻塞线程推进并违反运行时契约。我原本以为Continuation + GCD是替代方案,但该方案也存在反对观点。

反对Continuation + GCD方案的观点

应完全避免使用DispatchQueue。

我会避免引入GCD,因为它不参与协作式线程池,Swift并发无法合理调度系统资源、避免线程爆炸等。

那么,到底如何正确地让这个async函数在后台线程运行?


内容的提问来源于stack exchange,提问作者NSExceptional

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 22:42:36