C# async 和await 的面试题

C# async /await 高频面试题(含答案 + 解析)

这是 .NET 开发必考题,我整理了最常问、最容易踩坑的面试题,覆盖基础、原理、线程、异常、性能、实战,直接背会就能通关。

一、基础概念题(必问)

  1. 什么是 C# 中的 async /await?
    答案:async/await 是 C# 5.0 引入的异步编程语法糖,基于 Task 异步模型(TAP),用于以同步写法写异步代码,解决异步代码嵌套复杂、可读性差的问题。
    async:标记方法为异步方法
    await:等待异步操作完成,不阻塞线程
    核心:它不是创建线程,而是线程复用 + IO 等待时释放线程。
  2. async 方法的返回值有哪几种?
    答案(必考):
    Task:无返回值的异步方法(对应 void)
    Task:有返回值的异步方法
    void:仅用于事件处理(如按钮点击),绝对不要在业务代码使用
    ValueTask:高性能优化,减少内存分配
    禁忌:业务方法禁止返回 void,无法捕获异常、无法等待、无法取消。
  3. await 做了什么?会不会阻塞线程?
    答案:
    遇到 await:挂起当前异步方法,立即把线程归还线程池
    IO 完成后:恢复执行后续代码
    不会阻塞线程!这是和 Wait()/Result 最大的区别
    关键词:挂起方法 ≠ 阻塞线程。
    二、线程与同步上下文(高频坑点)
  4. async /await 会创建新线程吗?
    答案:绝大多数情况不会!
    IO 操作(网络、数据库、文件):不创建线程,纯内核等待
    CPU 操作:用 Task.Run() 才会切到线程池线程
    总结:async/await 是调度线程,不是创建线程。
  5. ConfigureAwait (false) 是什么?为什么要用?
    答案:
    await xxx.ConfigureAwait(false)
    作用:不需要回到原同步上下文(UI 线程 /ASP.NET 请求上下文)
    优点:减少开销、避免死锁、提升性能
    使用场景:类库、通用方法必须加;UI 主线程不要用
    三、死锁面试题(超级高频)
    题目:下面代码为什么会死锁?怎么解决?
    // 桌面/ASP.NET 环境
csharp 复制代码
public void Test()
{
    MethodAsync().Wait();
}

public async Task MethodAsync()
{
    await Task.Delay(100);
}

答案:

原因:

Wait() 阻塞主线程

await 完成后想回到原主线程,但线程已被阻塞 → 死锁

解决方案:

csharp 复制代码
await MethodAsync().ConfigureAwait(false);

或全程异步,不使用 Wait() / .Result。

四、异常捕获题

  1. async 方法中异常怎么捕获?
    答案:
    异步方法异常会封装到 Task 中
    必须 await Task 才能捕获异常
    用 try-catch 包裹 await
    示例:
csharp 复制代码
async Task Test()
{
    try
    {
        await DoAsync();
    }
    catch (Exception ex)
    {
        // 捕获成功
    }
}
  1. 多个异步异常怎么捕获?
    答案:Task.WhenAll 会抛出 AggregateException,用 .InnerExceptions 遍历所有异常。
    csharp
    运行
csharp 复制代码
try
{
    await Task.WhenAll(t1, t2, t3);
}
catch (AggregateException ex)
{
    var allEx = ex.InnerExceptions;
}

五、执行顺序题(必看)

题目:写出执行顺序

csharp 复制代码
运行
Console.WriteLine(1);
Test();
Console.WriteLine(4);

async Task Test()
{
    Console.WriteLine(2);
    await Task.Delay(100);
    Console.WriteLine(3);
}

答案:

1 → 2 → 4 → 3

解析:

async 方法开头同步执行

遇到 await 立即返回

后续代码是续行(Continuation),异步执行

六、实战与性能题

  1. async /await 优点?
    答案:
    代码扁平,无回调地狱
    不阻塞线程,高并发下吞吐量更高
    支持 try-catch,调试简单
    基于 Task,可组合、可取消、可异常处理
  2. 异步和多线程的区别?
    答案:
    多线程:靠线程并行(占资源)
    异步:IO 等待时释放线程,不占 CPU(高吞吐)
    关系:异步可以用多线程,但不是必须
  3. 如何并发执行多个异步?
    错误(串行):
csharp 复制代码
await a();
await b();
await c();

正确(并发):

csharp 复制代码
var t1 = a();
var t2 = b();
var t3 = c();
await Task.WhenAll(t1, t2, t3);
  1. Task.Run 和 async/await 的区别?
    答案:
    Task.Run:把同步方法丢到线程池,适合 CPU 密集
    async/await:原生异步,适合 IO 密集(网络、数据库、文件)
    七、高频简答题(背会直接用)
    async void 为什么不能用?无法捕获异常、无法等待、无法取消、程序易崩溃。
    await 和 Wait ()/Result 区别?await 不阻塞线程;Wait/Result 阻塞线程,会导致死锁。
    异步方法的性能好在哪里?IO 时释放线程,能处理更多请求,提升服务吞吐量。
    ValueTask 是什么?高性能结构体,减少 Task 堆分配,常用于高频调用的异步方法。
    终极总结(面试必背)
    1.async/await 是语法糖,基于 Task
    2.await 不阻塞线程,只挂起方法
    3.返回值优先 Task/Task,禁止 async void
    4.类库必须用 ConfigureAwait (false)
    5.不要用 Wait ()/Result,会死锁
    6.并发用 WhenAll,串行用 await
    7.IO 用异步,CPU 用 Task.Run
相关推荐
大鹏说大话2 小时前
打破边界:前后端分离架构下的跨域难题与破局之道
开发语言
人工智能AI技术2 小时前
C#接入CodeBuddy CLI实战:在.NET后端集成多AI Provider的全流程拆解
人工智能·c#
亚马逊云开发者2 小时前
MCP 协议实战:用 Amazon Bedrock 让 AI Agent 安全调用云服务的完整方案
开发语言·qt·安全
co_wait2 小时前
【C++ STL】排序算法
开发语言·c++·排序算法
地球驾驶员2 小时前
NX二次开发C#-----NXopen测量两个面的投影距离
c#
黑眼圈子2 小时前
Java正则表达式基础知识
java·开发语言·正则表达式
李昊哲小课2 小时前
Python 线性数据结构详解
开发语言·数据结构·python
jacsonchen2 小时前
MacOS升级ruby版本
开发语言·macos·ruby
李昊哲小课2 小时前
Python 数据结构示例
开发语言·数据结构·python