C#面试题更新 2026-08-03

在 C# 开发中处理异步方法异常有什么标准做法?

考察说明

考察对 C# 异步异常处理机制的理解。

回答思路

  1. 【回答框架 1】在 C# 中,异步方法中的异常通常通过 await 捕获。当 async 方法抛出异常时,该异常会被封装在返回的 Task 中,异常被观察的时机取决于如何消费这个 Task。
  2. 【回答框架 2】标准的处理方式是在调用异步方法时使用 try-catch 块包裹 await 表达式,这样捕获的是实际发生的异常。
  3. 【回答框架 3】对于多个并发异步任务,可以使用 Task.WhenAll 或 Task.WhenAny 组合,并在组合后的任务上捕获异常。WhenAll 会抛出第一个异常(除非使用异常聚合),但可以访问 Task 集合中的 Exception 属性获取所有异常。
  4. 【回答框架 4】对于基于事件的异步模式(如事件处理器),异常在处理内部被捕获并在 SynchronizationContext 上重新抛出,可能导致未处理异常,所以应使用 async void 修饰的事件处理器内部要特别小心,通常应确保所有异常都被捕获。
  5. 【回答框架 5】更高级的做法是使用 async 方法返回 Task 作为统一入口,调用方通过 await 或 Task.ContinueWith 处理异常;对于服务边界可用全局异常处理机制(如中间件或全局异常过滤器)记录并返回错误信息,而不中断整个程序。
  6. 【关键点 1】await 是捕获异步方法异常的主要方式。
  7. 【关键点 2】async void 事件处理器异常会直接抛出到同步上下文,容易导致崩溃,应尽量避免或确保内部捕获。
  8. 【关键点 3】Task.WhenAll 仅传播第一个异常,需要访问所有异常时需遍历任务状态。
  9. 【关键点 4】使用 CancellationToken 和逻辑重试可避免部分因异常导致的任务悬挂。
  10. 【易错点 1】仅调用 async 方法而不 await,异常不会被当前上下文观察,可能造成未处理异常。
  11. 【易错点 2】在 async void 方法中 try-catch 不能完全捕获所有异常,异常会直接抛出到同步上下文。
  12. 【易错点 3】当多个任务并发失败时,若用 await Task.WhenAll(taskArray),只能捕获第一个抛出的异常,后续异常仍会继续抛出。