C# 并发与异步编程详解
一、异步编程基础
1. async/await 模式
csharp
public async Task<string> GetDataAsync()
{
// 异步操作1
var result1 = await HttpClient.GetStringAsync("url1");
// 异步操作2
var result2 = await HttpClient.GetStringAsync("url2");
return result1 + result2;
}2. 返回类型
Task:无返回值的异步操作Task<T>:有返回值的异步操作ValueTask<T>:轻量级异步操作(性能优化)
二、并发控制
1. 锁机制
csharp
private readonly object _lock = new object();
void ThreadSafeMethod()
{
lock (_lock)
{
// 临界区代码
}
}2. 信号量
csharp
private SemaphoreSlim _semaphore = new SemaphoreSlim(3); // 允许3个并发
async Task AccessResource()
{
await _semaphore.WaitAsync();
try
{
// 受保护的资源访问
}
finally
{
_semaphore.Release();
}
}三、任务并行库(Task Parallel Library)
1. 任务创建
csharp
// 方式1:直接运行
Task.Run(() => Console.WriteLine("后台任务"));
// 方式2:显式创建
var task = new Task(() => { /* 工作 */ });
task.Start();2. 任务组合
csharp
// 等待所有任务完成
await Task.WhenAll(task1, task2, task3);
// 等待任意任务完成
await Task.WhenAny(task1, task2);
// 顺序执行多个任务
var result = await task1.ContinueWith(t => task2);四、并发集合
1. BlockingCollection
csharp
var bc = new BlockingCollection<int>(boundedCapacity: 10);
// 生产者
Task.Run(() =>
{
while (true) bc.Add(ProduceItem());
});
// 消费者
Task.Run(() =>
{
foreach (var item in bc.GetConsumingEnumerable())
{
ProcessItem(item);
}
});2. ConcurrentDictionary
csharp
var dict = new ConcurrentDictionary<string, int>();
dict.TryAdd("key", 1); // 线程安全添加
dict["key"] = 2; // 线程安全更新五、高级模式
1. 取消令牌(CancellationToken)
csharp
var cts = new CancellationTokenSource();
var token = cts.Token;
async Task LongRunningOperation()
{
while (true)
{
token.ThrowIfCancellationRequested();
await Task.Delay(1000);
}
}
// 调用取消
cts.CancelAfter(5000); // 5秒后取消2. 通道(Channel)
csharp
var channel = Channel.CreateUnbounded<int>();
// 写入者
async Task Writer()
{
for (int i = 0; i < 10; i++)
{
await channel.Writer.WriteAsync(i);
}
channel.Writer.Complete();
}
// 读取者
async Task Reader()
{
await foreach (var item in channel.Reader.ReadAllAsync())
{
Console.WriteLine(item);
}
}六、最佳实践
- 避免async void:始终返回Task,除了事件处理器
- 配置等待:
ConfigureAwait(false)减少上下文切换 - 错误处理:确保所有Task都有异常处理
- 资源释放:异步Dispose模式
csharp
await using (var resource = new AsyncResource())
{
// 使用资源
}- 性能考虑:
- 避免过度并行化
- 使用ValueTask减少分配
- 考虑使用IAsyncEnumerable处理流数据
这些技术组合使用可以构建高效、响应迅速的应用程序,同时保持代码的可维护性和线程安全性。