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

如何按顺序执行多个异步任务并在异常时继续执行?

异步任务顺序执行的异常处理问题

我希望按顺序执行多个异步任务,初始写法如下:

foreach (var msg in messages)
{
    await smtp.SendAsync(msg);
}

但我希望当其中某个任务失败时,其余任务仍能继续执行,并在最后抛出一个异常。这类似于WhenAll()的行为——执行所有任务,若有失败则在最后抛出AggregateException,但我找不到对应的顺序执行替代方案。

我查阅了文档并搜索相关内容后,未发现内置实现方式,于是手动处理异常,写法如下:

var exceptions = new List<Exception>();
foreach (var msg in messages)
{
    try
    {
        await smtp.SendAsync(msg).ConfigureAwait(false);
    }
    catch (Exception ex)
    {
        exceptions.Add(ex);
    }
}
if (exceptions.Count > 0) 
{
    throw new AggregateException(exceptions);
}

现提出以下问题:

  1. 是否存在我遗漏的.NET内置解决方案?
  2. 若没有内置方案,当前写法是否正确?使用ContinueWith链式调用并返回最终的“链式任务”是否更优(从而避免await/async带来的不必要状态机构建)?
  3. 我是否可以使用.NET内置的AggregateException,这是否属于不良实践?

回答

1. 不存在对应的内置解决方案

.NET没有提供和WhenAll()功能等价的顺序执行内置API。WhenAll()的核心是并行执行所有任务后汇总异常,而顺序执行的场景需要手动处理,你当前的思路是正确的。

2. 当前写法正确,ContinueWith无显著优势

  • 写法正确性:这段代码完全符合需求——按顺序执行每个异步任务,捕获所有执行异常,最后统一抛出AggregateException。ConfigureAwait(false)的使用也合理,能避免不必要的上下文切换(适用于不需要同步回原上下文的场景)。
  • ContinueWith对比:用ContinueWith链式构建任务确实可以规避async/await的状态机,但会大幅降低代码可读性。async/await的状态机开销在绝大多数业务场景下可以忽略,而代码的可维护性远重于这点微小的性能差异。除非你处于极端性能敏感的场景(比如每秒上万次的高频执行逻辑),否则完全没必要用ContinueWith替代当前写法。

3. 可以使用AggregateException,不属于不良实践

AggregateException本身就是为汇总多个异常的场景设计的,.NET自身的API(比如WhenAll())也会抛出该类型异常。只要你的场景需要集中反馈多个执行失败的异常,使用它完全合理,不属于不良实践。只需注意抛出时确保异常列表完整,不要遗漏捕获到的异常即可。


内容的提问来源于stack exchange,提问作者Alex from Jitbit

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 13:50:29