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

如何启动多个Async<'T>并行执行并逐个等待结果汇报进度?

F#原生Async实现方案

可以通过递归遍历异步任务列表并逐个等待完成的方式,实现并行执行+实时进度汇报,完全基于F#的Async类型,无需依赖Task。

核心思路

  • 将所有计算包装为惰性的Async<'T>,通过Async.StartChild启动所有任务,让它们并行运行
  • 递归处理已启动的任务列表,每完成一个任务就立即输出进度,再继续处理剩余任务

完整实现代码

open System

// 模拟耗时纯函数
let expensiveComputation x =
    let rnd = Random()
    Threading.Thread.Sleep(rnd.Next(1000, 5000))
    x * 2

// 启动所有异步任务,返回正在运行的异步句柄列表
let startAllAsync computations =
    computations
    |> List.map (fun comp -> async {
        let! runningTask = Async.StartChild(comp)
        return runningTask
    })

// 递归处理任务,实时汇报进度
let rec processTasksAsync remaining completed total = async {
    match remaining with
    | [] ->
        printfn "\n所有任务完成!总计 %d 个" total
        return []
    | task :: rest ->
        let! result = task
        let newCompleted = completed + 1
        printfn "任务完成:结果=%d,进度 %d/%d" result newCompleted total
        let! restResults = processTasksAsync rest newCompleted total
        return result :: restResults
}

// 主程序示例
let main () = async {
    let inputs = [1; 2; 3; 4; 5; 6]
    let totalTasks = inputs.Length
    // 包装为异步计算
    let asyncComputations = inputs |> List.map (fun x -> async { return expensiveComputation x })
    // 启动所有并行任务
    let runningTasks = startAllAsync asyncComputations
    // 处理任务并实时输出进度
    let! allResults = processTasksAsync runningTasks 0 totalTasks
    return allResults
}

// 运行程序
Async.RunSynchronously(main())

关键细节说明

  • Async.StartChild的作用:Async本身是惰性的,Async.StartChild会立即启动异步任务并返回一个可等待的句柄,确保所有任务并行执行。
  • 递归处理的优势:不需要等待全部任务完成,每完成一个就立即更新进度,完全符合实时展示的需求。
  • 纯F#风格:全程使用F#原生Async类型和递归模式,没有引入任何C#风格的TaskAPI,保持函数式编程的简洁性。

典型输出效果

任务完成:结果=4,进度 1/6
任务完成:结果=2,进度 2/6
任务完成:结果=6,进度 3/6
任务完成:结果=8,进度 4/6
任务完成:结果=10,进度 5/6
任务完成:结果=12,进度 6/6

所有任务完成!总计 6 个

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 05:02:47