异步编程 #
一、异步编程概述 #
1.1 为什么需要异步 #
- 避免阻塞UI线程
- 提高响应性
- 提高资源利用率
1.2 async/await特点 #
- 语法简洁
- 非阻塞
- 基于Task
二、async关键字 #
2.1 异步方法 #
csharp
public async Task DoWorkAsync()
{
await Task.Delay(1000);
Console.WriteLine("工作完成");
}
public async Task<int> CalculateAsync()
{
await Task.Delay(1000);
return 42;
}
public async Task<string> GetDataAsync()
{
await Task.Delay(1000);
return "数据";
}
2.2 async void #
csharp
public async void FireAndForget()
{
await Task.Delay(1000);
Console.WriteLine("完成");
}
private async void Button_Click(object sender, EventArgs e)
{
await LoadDataAsync();
}
2.3 异步Main #
csharp
public static async Task Main(string[] args)
{
await DoWorkAsync();
}
三、await关键字 #
3.1 等待Task #
csharp
public async Task ProcessAsync()
{
await Task.Delay(1000);
Task<int> task = Task.Run(() => Calculate());
int result = await task;
await Task.WhenAll(task1, task2);
}
3.2 await行为 #
csharp
public async Task ExampleAsync()
{
Console.WriteLine("开始");
await Task.Delay(1000);
Console.WriteLine("延迟后");
}
3.3 ConfigureAwait #
csharp
public async Task ProcessAsync()
{
await Task.Delay(1000).ConfigureAwait(false);
string data = await GetDataAsync().ConfigureAwait(false);
}
四、异步模式 #
4.1 Task-based异步模式(TAP) #
csharp
public class DataService
{
public async Task<string> GetDataAsync()
{
await Task.Delay(1000);
return "数据";
}
public async Task SaveDataAsync(string data)
{
await Task.Delay(1000);
}
}
4.2 I/O绑定异步 #
csharp
public async Task<string> ReadFileAsync(string path)
{
using var reader = new StreamReader(path);
return await reader.ReadToEndAsync();
}
public async Task WriteFileAsync(string path, string content)
{
await using var writer = new StreamWriter(path);
await writer.WriteAsync(content);
}
4.3 CPU绑定异步 #
csharp
public async Task<int> CalculateAsync(int n)
{
return await Task.Run(() =>
{
int result = 0;
for (int i = 0; i < n; i++)
{
result += i;
}
return result;
});
}
五、异步流 #
5.1 IAsyncEnumerable #
csharp
public async IAsyncEnumerable<int> GenerateNumbersAsync(int count)
{
for (int i = 0; i < count; i++)
{
await Task.Delay(100);
yield return i;
}
}
await foreach (var number in GenerateNumbersAsync(10))
{
Console.WriteLine(number);
}
5.2 异步迭代器 #
csharp
public async IAsyncEnumerable<string> ReadLinesAsync(string path)
{
using var reader = new StreamReader(path);
while (await reader.ReadLineAsync() is string line)
{
yield return line;
}
}
await foreach (var line in ReadLinesAsync("data.txt"))
{
Console.WriteLine(line);
}
六、ValueTask #
6.1 ValueTask #
csharp
public ValueTask<int> GetValueAsync(bool useCache)
{
if (useCache && _cachedValue.HasValue)
{
return new ValueTask<int>(_cachedValue.Value);
}
return new ValueTask<int>(FetchValueAsync());
}
private async Task<int> FetchValueAsync()
{
await Task.Delay(1000);
_cachedValue = 42;
return _cachedValue.Value;
}
6.2 ValueTask vs Task #
csharp
public ValueTask<string> GetDataAsync()
{
if (_cache.TryGetValue(key, out string cached))
{
return new ValueTask<string>(cached);
}
return new ValueTask<string>(FetchFromServerAsync());
}
七、异步最佳实践 #
7.1 避免async void #
csharp
public async Task DoWorkAsync()
{
await Task.Delay(1000);
}
public async void BadExample()
{
await Task.Delay(1000);
}
7.2 异步方法命名 #
csharp
public async Task<string> GetDataAsync()
public async Task SaveAsync(string data)
public async Task<bool> ExistsAsync(int id)
7.3 避免同步等待 #
csharp
public async Task GoodExample()
{
await Task.Delay(1000);
}
public void BadExample()
{
Task.Delay(1000).Wait();
Task.Delay(1000).Result;
}
7.4 取消支持 #
csharp
public async Task<string> GetDataAsync(CancellationToken cancellationToken = default)
{
using var client = new HttpClient();
return await client.GetStringAsync("https://api.example.com/data", cancellationToken);
}
八、实战示例 #
8.1 异步HTTP客户端 #
csharp
public class ApiClient
{
private readonly HttpClient _client = new();
public async Task<T?> GetAsync<T>(string url, CancellationToken cancellationToken = default)
{
var response = await _client.GetAsync(url, cancellationToken);
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync(cancellationToken);
return JsonSerializer.Deserialize<T>(json);
}
public async Task PostAsync<T>(string url, T data, CancellationToken cancellationToken = default)
{
var json = JsonSerializer.Serialize(data);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _client.PostAsync(url, content, cancellationToken);
response.EnsureSuccessStatusCode();
}
}
8.2 异步数据加载 #
csharp
public class DataLoader
{
public async Task<List<User>> LoadUsersAsync()
{
var users = new List<User>();
await foreach (var user in FetchUsersAsync())
{
users.Add(user);
}
return users;
}
private async IAsyncEnumerable<User> FetchUsersAsync()
{
for (int page = 1; ; page++)
{
var batch = await FetchPageAsync(page);
if (batch.Count == 0) yield break;
foreach (var user in batch)
{
yield return user;
}
}
}
private async Task<List<User>> FetchPageAsync(int page)
{
await Task.Delay(100);
return new List<User>();
}
}
九、总结 #
异步编程要点:
| 要点 | 说明 |
|---|---|
| async | 标记异步方法 |
| await | 等待异步操作 |
| Task | 异步返回类型 |
| ValueTask | 高性能异步 |
| IAsyncEnumerable | 异步流 |
下一步,让我们学习线程同步!
最后更新:2026-03-26