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

C#多线程场景下ConcurrentBag<T>与List<T>的选型及性能疑问

关于并行线程中List与ConcurrentBag的使用分析

1. 当前场景下不需要使用ConcurrentBag

你的代码里,var b = new List<T>();是每个异步任务内部的局部变量——每个任务都会创建独立的List实例,"do something"的操作只在当前任务的上下文里对自己的实例进行,不存在多个线程同时读写同一个List对象的情况。这种场景下List是完全安全的,不需要换成ConcurrentBag。

2. 什么时候才需要ConcurrentBag

只有当多个线程/任务需要同时读写同一个集合实例时,才必须使用线程安全集合(比如ConcurrentBag)。举个例子:如果把b的创建移到所有任务外面,多个任务都对同一个b进行Add/Remove操作,那此时List会因为非线程安全出现数据错乱,这时候才需要替换成ConcurrentBag或者手动加锁保护List。

3. 性能与写法优劣对比

  • 性能上List完胜:ConcurrentBag为了实现线程安全,内部做了大量同步逻辑(比如线程本地存储、分区锁等),这些都会带来额外的性能开销。在不需要线程安全的场景下用ConcurrentBag,纯粹是无意义的性能浪费。
  • 写法上List更简洁:List是C#里最常用的集合类,API更直观,代码可读性更高,不需要额外引入线程安全集合的概念。

额外注意:代码中的潜在逻辑问题

你的代码里多个任务都执行a["xxx"] = b;,ConcurrentDictionary的索引器赋值是线程安全的,但最终a["xxx"]只会保留最后一个完成的任务所赋值的b实例,前面所有任务的b都会被覆盖。如果你的业务逻辑是要把所有任务的结果合并到同一个集合里,那这种写法是错误的,需要改成:

// 先确保a["xxx"]存在对应的ConcurrentBag<T>
if (!a.TryGetValue("xxx", out var bag))
{
    bag = new ConcurrentBag<T>();
    a.TryAdd("xxx", bag);
}
// 然后每个任务往同一个bag里添加元素
bag.Add(xxx);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 09:55:19