Skip to content

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);
    }
}

六、最佳实践

  1. 避免async void:始终返回Task,除了事件处理器
  2. 配置等待ConfigureAwait(false)减少上下文切换
  3. 错误处理:确保所有Task都有异常处理
  4. 资源释放:异步Dispose模式
csharp
await using (var resource = new AsyncResource())
{
    // 使用资源
}
  1. 性能考虑
    • 避免过度并行化
    • 使用ValueTask减少分配
    • 考虑使用IAsyncEnumerable处理流数据

这些技术组合使用可以构建高效、响应迅速的应用程序,同时保持代码的可维护性和线程安全性。

✨ 网站运行时间: 3年11月15天 ❤️ 道阻且长,行则将至 - 微信号: heikedreamer