You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中多个异步函数并发修改List<T>是否会引发并发问题?

多个异步函数并发修改List会导致并发问题吗?

会,绝对会出现并发问题。

List<T>是.NET中常用的集合类型,但它不是线程安全的——所有公共方法(包括Add)都没有内置同步机制。当多个异步任务(可能在不同线程执行)同时调用Add修改同一个List<T>实例时,会触发竞态条件,引发各种不可预期的问题:

  • 元素被覆盖或丢失:两个线程同时执行Add时,可能同时写入内部数组的同一位置
  • 计数异常:Count属性值与实际元素数量不符
  • 抛出异常:比如IndexOutOfRangeException,或集合内部结构损坏导致的其他错误

解决方案

针对你的业务场景,有几种可靠的处理方式:

1. 使用线程安全集合ConcurrentBag<T>

ConcurrentBag<T>是.NET专为多线程并发添加操作设计的线程安全集合,直接替换List<T>即可,无需额外同步代码:

var errors = new ConcurrentBag<Error>();

var awaitedTasks = new List<Task>();
awaitedTasks.Add(funcA(errors));
awaitedTasks.Add(funcB(errors));
awaitedTasks.Add(funcC(errors));
awaitedTasks.Add(funcD(errors));

await Task.WhenAll(awaitedTasks);

2. 手动添加锁同步

如果必须使用List<T>,可以在每个函数的Add操作外添加全局锁,确保同一时间只有一个线程修改集合:

// 全局锁对象,确保所有函数共用同一个锁
private static readonly object _errorListLock = new object();

// 示例异步函数
public async Task funcA(List<Error> errors)
{
    // 执行业务逻辑
    var error = await GetSomeError();
    
    // 加锁后修改List
    lock (_errorListLock)
    {
        errors.Add(error);
    }
}

3. 避免共享状态,合并结果(推荐)

让每个异步函数独立返回自己的错误列表,最后统一合并,完全规避并发修改问题:

// 修改异步函数为返回Task<List<Error>>
var taskList = new List<Task<List<Error>>>
{
    funcA(),
    funcB(),
    funcC(),
    funcD()
};

// 等待所有任务完成,合并结果
var allErrors = await Task.WhenAll(taskList);
var errors = allErrors.SelectMany(list => list).ToList();

这种方式不需要处理线程同步,逻辑更清晰,也没有锁带来的性能开销。

内容的提问来源于stack exchange,提问作者Anuj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 16:43:00