C#中的Async和Await:如何使用及何时使用(逐步教程)

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

C#中的Async和Await:拯救应用程序免于“卡死”

\n\n

您是否曾经运行过一个C#程序,点击按钮后界面“冻结”了几秒钟?或者,您的服务器在处理一个“繁重”请求时,停止响应新请求?熟悉吗?这是同步代码的经典问题——执行线程在等待操作(如读取文件、数据库查询、HTTP调用)完成时被阻塞。

\n\n

这个问题的解决方案是异步编程。在C#中,主要的工具是关键字async和await。如果您曾经问过自己:“如何以及何时使用async和await?”——您来对地方了。在本教程中,我们将从基础到最佳实践逐一讲解,帮助您编写快速、响应灵敏且可扩展的代码。

\n\n

本材料基于Stack Overflow上一个真实的热门问题,该问题获得了数千次浏览。我们将其改编为教育内容,并添加了代码示例和清晰的解释。

\n\n

什么是async和await?简单来说

\n\n

想象一下,您是一位主厨(您的程序)。您需要准备晚餐。其中一道菜是汤,需要煮30分钟。在同步世界里,您会站在炉子旁,只是等着汤煮好,什么也不做。很傻,对吧?

\n\n

异步就是您把汤放上去煮(async),不等它煮好,就开始切沙拉、摆桌子、做其他事情。当汤煮好时,您再回来处理它(await)。您没有浪费时间——您很高效。

\n\n
    \n
  • async —— 方法的修饰符,告诉编译器:“此方法包含异步操作。当我遇到await时,不要阻塞线程。”
  • \n
  • await —— 应用于任务(Task)的操作符。它说:“暂停此方法的执行,直到任务完成,但不要阻塞线程。一旦任务完成,从该位置继续执行。”
  • \n
\n\n

重要提示:await不会阻塞线程。它将控制权返回给调用代码,而线程继续执行其他工作。

\n\n

何时使用async和await?

\n\n

这是最常见的问题。答案很简单:每当您执行可能需要很长时间的操作(I/O密集型操作),并且您不希望阻塞线程时。

\n\n

以下是典型场景:

\n
    \n
  • 网络请求: HTTP调用(HttpClient)、WebSocket操作。
  • \n
  • 文件操作: 读取/写入大文件、流操作。
  • \n
  • 数据库查询: Entity Framework、ADO.NET、Dapper。
  • \n
  • Web服务操作: WCF、REST API。
  • \n
  • 任何输入/输出(I/O)操作: 访问磁盘、网络、打印机。
  • \n
\n\n

何时不应该使用async和await?

\n
    \n
  • CPU密集型操作: 如果您的任务需要大量计算(3D渲染、视频处理、复杂数学计算),async/await没有帮助。这里应该使用Task.Run或Parallel来在多个CPU核心上并行处理。
  • \n
  • 在类构造函数中: 构造函数不能是async。请使用工厂方法(public static async Task<MyClass> CreateAsync())。
  • \n
  • 在属性的getter/setter中: 它们也不能是async。请使用方法。
  • \n
\n\n

它是如何工作的?通过代码示例分析

\n\n

让我们看一段实际代码。假设我们从远程服务器加载数据。

\n\n

糟糕的示例(同步)

\n
public string GetDataFromWeb()\n{\n    usi                

博客

书籍推荐