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

如何实现保留异常顺序的自定义Task.WhenAll方法?

实现按位置顺序传播异常的Task.WhenAll替代方法

.NET 8中,非泛型的Task.WhenAll行为发生了变更——现在它会按异常发生的时间顺序抛出,而非原有的任务数组位置顺序。如果你的测试依赖旧版按位置排序异常的行为,可以实现以下替代方法:

方法签名

/// <summary>
/// 创建一个在所有提供的任务完成后才完成的任务。
/// 该任务会按任务数组中的位置顺序(而非时间顺序)包含故障任务的异常。
/// </summary>
public static Task WhenAll_OrderedExceptions(params Task[] tasks)

预期行为示例

测试代码:

async Task DoAsync(string title, int delay)
{
    await Task.Delay(delay);
    throw new Exception(title);
}

Task t1 = DoAsync("A", 200);
Task t2 = DoAsync("B", 100);

try
{
    WhenAll_OrderedExceptions(t1, t2).Wait();
}
catch (AggregateException aex)
{
    Console.Write($"Error message: {aex.Message}");
}

预期输出:

Error message: One or more errors occurred. (A) (B)

(注:.NET 8原生Task.WhenAll会输出Error message: One or more errors occurred. (B) (A),不符合需求)

实现代码

public static async Task WhenAll_OrderedExceptions(params Task[] tasks)
{
    // 等待所有任务完成,无论成功或失败
    await Task.WhenAll(tasks).ConfigureAwait(false);
    
    // 按任务数组的原始顺序收集所有异常
    var exceptions = new List<Exception>();
    foreach (var task in tasks)
    {
        if (task.IsFaulted)
        {
            exceptions.AddRange(task.Exception.InnerExceptions);
        }
    }
    
    // 存在异常时,抛出按位置排序的AggregateException
    if (exceptions.Count > 0)
    {
        throw new AggregateException(exceptions);
    }
}

实现说明

  1. 先调用原生Task.WhenAll等待所有任务完成,确保能获取到所有任务的执行状态。
  2. 遍历任务数组,严格按原始位置顺序收集每个故障任务的内部异常。
  3. 若收集到异常,抛出包含有序异常的AggregateException;无异常则方法正常完成。

该实现完全匹配旧版Task.WhenAll的异常排序逻辑,能满足依赖旧行为的测试需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 18:35:04