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

C#无await的async方法异常未捕获及UnobservedTaskException不触发问题

问题1:未加await的async Task方法异常无法被外层catch捕获的原因

只要方法被async Task修饰,无论内部是否包含await关键字,编译器都会对方法做状态机改写:方法执行过程中抛出的异常不会直接向上抛给调用方,而是会被封装到方法返回的Task对象中,同时将该Task标记为Faulted状态。
你调用ThrowsAsync()时没有加await,相当于直接丢弃了返回的Task对象,外层try/catch只能捕获方法调用过程中同步抛出的异常,被打包到Task中的异常不会同步触发,因此不会被catch块捕获。
如果你需要该方法的异常和普通同步方法一样直接向上抛出,只需要去掉方法的async关键字即可,无返回值的场景下直接返回Task.CompletedTask,此时抛出的异常就属于同步异常,可以被外层catch捕获。

问题2:UnobservedTaskException事件未触发的原因

TaskScheduler.UnobservedTaskException的触发有两个必要前提:

  1. 封装了异常的故障Task对象被GC回收
  2. 回收之前从未对该Task的异常做过观察操作(观察操作包括await、访问Task的Exception属性、调用Wait()方法等)
    你的代码中Console.ReadLine()会一直阻塞主线程,程序既没有退出也没有触发GC回收动作,封装了异常的Task对象仍存活在内存中,自然不会触发未观察异常事件。你可以在原有调用逻辑后主动触发GC验证:
try
{                
    ThrowsAsync();
}
catch (Exception ex)
{
    Console.WriteLine($"Caught in try/catch  : {ex.Message}");
}
// 新增GC触发代码
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

运行后即可看到UnobservedTaskException事件的输出内容。
另外注意:.NET Core 2.0及以上版本(包括你使用的.NET 5)中,未观察的Task异常默认不会导致进程崩溃,仅会触发该事件,和.NET Framework的旧行为存在差异。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 02:06:01