C# 异步编程简介
异步编程是现代 C# 开发中的关键概念之一。在高负载 Web 应用、微服务和云解决方案的时代,有效处理异步操作的能力已成为每位 .NET 开发者的必备技能。
异步编程的主要目标是在等待耗时操作(I/O、网络操作、数据库查询)时不阻塞执行线程。相反,线程会被释放出来处理其他任务,从而显著提高应用程序的性能和可扩展性。
在本文中,我们将介绍:
- C# 中 async/await 的基础知识
- 使用 Task 类
- 编写异步方法的规则
- 常见错误以及如何避免它们
C# 中 async/await 的基础知识
C# 中异步编程的关键范式建立在两个关键字之上:async 和 await。它们是在 C# 5.0 中引入的,从此成为处理异步操作的标准。
async/await 的工作原理
async 关键字用于声明异步方法。await 应用于 Task,以暂停方法的执行直到其完成,同时不阻塞当前线程。
public async Task<string> GetDataAsync(){ // 模拟异步 HTTP 请求 using var client = new HttpClient(); string result = await client.GetStringAsync("https://api.example.com/data"); return result;}
public async Task ProcessAsync(){ string data = await GetDataAsync(); Console.WriteLine($"数据已接收: {data}");}需要理解的重要一点是:await 不会阻塞线程。它将控制权返回给调用代码,当任务完成时,方法会从同一位置继续执行。
异步方法的返回类型
异步方法可以返回三种类型之一:
Task— 用于不返回值的方法Task<T>— 用于返回类型 T 的值的方法ValueTask<T>— 用于结果通常同步可用的高性能场景
// 无返回值public async Task SaveDataAsync(string data){ await File.WriteAllTextAsync("data.txt", data);}
// 有返回值public async Task<int> CalculateSumAsync(int a, int b){ await Task.Delay(100); // 模拟耗时操作 return a + b;}
// 使用 ValueTask 进行优化public async ValueTask<bool> CheckCacheAsync(string key){ if (_cache.ContainsKey(key)) return true; await Task.Delay(50); return false;}Task 的高级用法
Task 类是 C# 异步编程的基础。让我们看看最有用的方法和模式。
并行执行任务
Task.WhenAll 和 Task.WhenAny 方法允许你高效地管理多个异步操作。
public async Task ProcessMultipleRequestsAsync(){ var task1 = FetchDataAsync("url1"); var task2 = FetchDataAsync("url2"); var task3 = FetchDataAsync("url3"); // 等待所有任务完成 await Task.WhenAll(task1, task2, task3); Console.WriteLine("所有请求已完成");}
public async Task<string> GetFirstResponseAsync(){ var task1 = FetchDataAsync("url1"); var task2 = FetchDataAsync("url2"); // 等待第一个任务完成 Task<string> completedTask = await Task.WhenAny(task1, task2); return await completedTask;}