如何正确捕获async异步方法内部抛出的异常?
问题原因
- 原代码中
Task.Run(async () => await DoTask())仅提交了后台异步任务,没有等待任务执行完成,try块在任务抛出异常前就已经执行结束,异常无法被当前catch捕获。未被观察的Task异常默认会被运行时忽略。
解决方案
方案1:使用异步Main方法(推荐,C# 7.1及以上版本支持)
直接await任务执行,异常会被正常抛出到await位置:
private static async Task DoTask() { await Task.Delay(10000); throw new Exception("Exception!"); } public static async Task Main(string[] args) { try { // 不需要额外包装Task.Run的场景可以直接写 await DoTask() await Task.Run(async () => await DoTask()); } catch (Exception ex) { Console.WriteLine(ex.Message); } Console.WriteLine("End"); Console.ReadKey(); }
方案2:同步阻塞等待(兼容旧版C#)
如果不能使用异步Main,可以调用GetAwaiter().GetResult()或者Wait()等待任务完成:
public static void Main(string[] args) { try { // GetAwaiter().GetResult()会直接抛出原始异常,不会包装为AggregateException Task.Run(async () => await DoTask()).GetAwaiter().GetResult(); // 如果用Wait()需要捕获AggregateException解包: // Task.Run(async () => await DoTask()).Wait(); } catch (Exception ex) { Console.WriteLine(ex.Message); } // 使用Wait()的场景需要替换catch为: // catch (AggregateException ae) // { // foreach (var innerEx in ae.InnerExceptions) // { // Console.WriteLine(innerEx.Message); // } // } Console.WriteLine("End"); Console.ReadKey(); }
内容的提问来源于stack exchange,提问作者user788454
相关产品推荐
相关产品推荐

