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

Swift异步Task中更新CLI进度条出现并发修改错误如何解决?

错误原因

该报错是Swift并发安全检查触发的:你定义的ProgressBar是可变结构体,而Task闭包属于并发执行的代码,编译器无法保证你在并发上下文中修改外部bar变量的操作是线程安全的,因此直接拦截编译。

解决方案1:主Actor调度更新(推荐用于CLI场景)

CLI进度条的渲染属于终端输出类操作,本身需要在主线程执行避免输出乱序,你可以直接将进度条更新操作调度到主Actor执行即可:

var bar = ProgressBar(count: 100)

let waiter = Task {
    do {
        for try await output in session.outputs {
            switch output {
                case .requestProgress(let request, let fractionComplete):
                    let progress = Int(fractionComplete * 100)
                    // 将修改操作切到主Actor执行,保证线程安全
                    await MainActor.run {
                        bar.setValue(progress)
                    }
            }
        }
    } catch {
        logger.error("Output: ERROR = \(String(describing: error))")
        Foundation.exit(0)
    }
}

解决方案2:Actor封装状态管理

如果你需要脱离主线程管理进度状态,可以自定义Actor来封装进度条的所有变更操作,保证所有修改串行执行:

// 自定义Actor保证进度条修改线程安全
actor ProgressStateManager {
    private var bar: ProgressBar
    
    init(totalCount: Int) {
        bar = ProgressBar(count: totalCount)
    }
    
    func update(fractionComplete: Double) {
        bar.setValue(Int(fractionComplete * 100))
    }
}

// 调用侧代码
let progressManager = ProgressStateManager(totalCount: 100)
let waiter = Task {
    do {
        for try await output in session.outputs {
            switch output {
                case .requestProgress(let request, let fractionComplete):
                    // 异步调用Actor的更新方法,自动保证线程安全
                    await progressManager.update(fractionComplete: fractionComplete)
            }
        }
    } catch {
        logger.error("Output: ERROR = \(String(describing: error))")
        Foundation.exit(0)
    }
}

内容的提问来源于stack exchange,提问作者Alexander Hörl

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 05:54:03