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

如何在C#的for循环中并发运行异步函数并捕获所有错误

问题分析与解决方案

你的代码存在两个核心问题,导致无法捕获所有异常甚至出现未处理异常:

  1. 同步异常直接抛出:如果SomeAsyncFunc在执行到第一个await之前就抛出异常(比如同步逻辑出错),这个异常会在调用SomeAsyncFunc(item.Index)时直接同步抛出,不会被包装到Task中,自然无法被后续的try/catch捕获。
  2. Task.WhenAll仅抛出第一个异常:即使所有异常都是异步抛出的,await Task.WhenAll也只会将第一个发生的异常抛进catch块,其他任务的异常会被忽略,无法全部打印。

修复方案:为每个任务单独捕获异常并收集结果

通过包装每个异步任务,确保同步/异步异常都被捕获,同时收集所有任务的执行状态,最终遍历输出所有错误:

public async Task RunEachItem()
{
    var tasks = new List<Task<(int ItemIndex, Exception Error)>>();

    foreach (var item in Items)
    {
        // 捕获循环变量,避免闭包陷阱
        int itemIndex = item.Index;
        tasks.Add(RunTaskWithErrorCapture(itemIndex));
    }

    // 等待所有任务完成,获取所有结果
    var executionResults = await Task.WhenAll(tasks);

    // 遍历所有结果,打印错误信息
    foreach (var result in executionResults)
    {
        if (result.Error != null)
        {
            Console.WriteLine($"项 {result.ItemIndex} 执行出错:{result.Error.Message}");
        }
    }
}

/// <summary>
/// 包装异步任务,捕获所有异常并返回执行结果
/// </summary>
private async Task<(int ItemIndex, Exception Error)> RunTaskWithErrorCapture(int index)
{
    try
    {
        await SomeAsyncFunc(index);
        return (index, null);
    }
    catch (Exception ex)
    {
        return (index, ex);
    }
}

public async Task SomeAsyncFunc(int index)
{
    // 模拟异步处理逻辑
    await Task.Delay(50);
    throw new Exception($"some error for item {index}");
}

方案说明

  • 同步/异步异常全覆盖:每个任务都被包裹在独立的try/catch中,无论是SomeAsyncFunc里的同步逻辑异常,还是异步阶段抛出的异常,都会被捕获并包装到返回值中。
  • 避免闭包陷阱:在循环内部捕获item.Index到局部变量,防止所有任务共享循环变量的引用,导致最终使用的都是最后一个项的索引。
  • 收集所有错误:通过返回值记录每个任务的执行状态,最终遍历所有结果即可输出全部错误信息,不会遗漏任何异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 13:50:04