C# 异步编程:初学者完整指南

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

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

开始课程

C# 异步编程:初学者完整指南

\n\n

异步编程是现代 C# 开发中的关键概念之一。它使您的应用程序能够保持响应,而不会在执行长时间操作(如读取文件、数据库查询或 HTTP 调用)时阻塞执行线程。在本指南中,我们将通过实际示例讲解 C# 异步编程的基础知识。

\n\n

什么是异步编程,为什么需要它?

\n\n

在同步编程中,代码按顺序执行。如果您调用一个等待服务器响应 5 秒的方法,整个线程(UI 或工作线程)将停滞。应用程序会“卡住”。异步编程解决了这个问题:方法不是阻塞线程,而是将控制权返回给调用代码,并在结果准备好时通知调用方。

\n\n

异步的主要优势:

\n
    \n
  • UI 响应性 — 界面在长时间操作期间不会卡住。
  • \n
  • 可扩展性 — 服务器应用程序可以处理更多请求,而无需创建新线程。
  • \n
  • 效率 — 释放的线程可用于其他任务。
  • \n
\n\n

C# 中 async/await 的基础知识

\n\n

关键字 async 和 await 是 C# 异步编程的基础。它们从 C# 5.0 开始引入,使异步代码几乎和同步代码一样简单。

\n\n

使用规则:

\n
    \n
  • 方法使用关键字 async 标记。
  • \n
  • 返回类型应为 Task、Task<T> 或 void(仅用于事件处理程序)。
  • \n
  • 在方法内部,使用关键字 await 调用其他异步方法。
  • \n
\n\n

简单示例:

\n
using System;\nusing System.Net.Http;\nusing System.Threading.Tasks;\n\nclass Program\n{\n    static async Task Main(string[] args)\n    {\n        Console.WriteLine("开始下载...");\n        string content = await DownloadWebPageAsync("https://example.com");\n        Console.WriteLine($"已下载字符数:{content.Length}");\n    }\n\n    static async Task<string> DownloadWebPageAsync(string url)\n    {\n        using HttpClient client = new HttpClient();\n        string result = await client.GetStringAsync(url);\n        return result;\n    }\n}
\n\n

请注意:Main 方法也被标记为 async Task — 从 C# 7.1 开始这是允许的。

\n\n

Task、Task<T> 和 ValueTask 类型

\n\n

在 C# 异步编程中,使用三种主要的返回值类型:

\n\n
    \n
  • Task — 用于不返回值的方法(类似于 void)。
  • \n
  • Task<T> — 用于返回类型 T 值的方法。
  • \n
  • ValueTask<T> — 针对结果通常可同步获取的场景(例如从缓存中)的优化版本。
  • \n
\n\n

Task<T> 示例:

\n
static async Task<int> CalculateSumAsync(int a, int b)\n{\n    await Task.Delay(1000); // 模拟长时间工作\n    return a + b;\n}\n\n// 调用:\nint result = await CalculateSumAsync(5, 3);\nConsole.WriteLine(result); // 8
\n\n

异步方法中的错误处理

\n\n

异步方法中的异常使用标准的 try-catch 块处理。但有一个重要的细节:异常会保存在 Task 对象中,并在使用 await 时重新“抛出”。

\n\n
static async Task<string> ReadFileAsync(string path)\n{\n    try\n    {\n        string content = await File.ReadAllTextAsync(path);\n        return content;\n    }\n    catch (FileNotFoundException ex)\n    {\n        Console.WriteLine($"文件未找到:{ex.Message                

博客

书籍推荐