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

Task异常传播异常:try-catch未捕获Task抛出异常的原因排查

问题:Task.Run抛出的异常未被外层try-catch捕获的原因

我在Visual Studio 2022、C#10、.NET 6环境下运行Task并行库的异常处理示例代码时,发现一个异常现象:Task.Run中抛出的异常无法传播到外层的try-catch块;但只要添加Thread.Sleep(10)或者改用task.Wait(10)这类延迟操作,异常就能正常被捕获。想知道这是编译器优化还是BUG?

示例代码如下:

public class Program
{
    public static void Main()
    {
        var task = Task.Run(
           () => {
               //Thread.Sleep(10); //取消注释后异常会被传播  
               throw new CustomException("This exception is expected!");
           });

        try
        {
            task.Wait(); //改用task.Wait(1)也能捕获异常  
        }
        catch (AggregateException ae)
        {
            foreach (var ex in ae.InnerExceptions)
            {
                // 处理自定义异常
                if (ex is CustomException)
                {
                    Console.WriteLine(ex.Message);
                }
                // 重新抛出其他异常
                else
                {
                    throw ex;
                }
            }
        }
    }
    class CustomException : Exception
    {
        public CustomException(string s) : base(s) { }
    }
}

原因分析

这既不是编译器优化也不是BUG,而是Task任务调度时机与主线程执行顺序引发的竞态条件:

  • 当Task.Run执行的委托逻辑极短(比如直接抛出异常),任务可能在主线程调用task.Wait()之前就已经完成并进入故障状态,但由于.NET任务调度和线程同步机制的细微延迟,主线程调用Wait()时,Task实例可能还没来得及将异常关联自身。
  • 添加Thread.Sleep(10)或使用Wait(10)本质上是给主线程留出等待时间,让Task的异常能被正确关联到Task对象,此时Wait()就能捕获到包含异常的AggregateException。
  • 这种情况属于多线程环境下的极端场景,实际业务中几乎不会遇到——大多数Task执行的逻辑都有一定耗时,不会触发这种竞态条件,因此官方文档未专门提及。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 18:20:48