ConcurrentBag – 添加多个项目?

有没有办法一次向ConcurrentBag添加多个项目,而不是一次添加一个? 我没有在ConcurrentBag上看到AddRange()方法,但是有一个Concat()。 但是,这对我不起作用:

ConcurrentBag objectList = new ConcurrentBag(); timeChunks.ForEach(timeChunk => { List newList = Foo.SomeMethod(x => x.SomeReadTime > timeChunk.StartTime); objectList.Concat(newList); }); 

这段代码曾经在Parallel.ForEach()中,但我将其更改为上面所以我可以对其进行故障排除。 变量newList确实有对象,但是在objectList.Concat 行之后,objectList总是有0个对象。 Concat 不能那样工作吗? 我是否需要使用Add()方法一次一个地向ConcurrentBag添加项目?

是的:)

Concat可能是Enumerable扩展之一。 它不会向ConcurrentBag添加任何内容,它只返回一些包含原始包的时髦对象以及您尝试添加的任何内容。

请注意, Concat的结果不再是ConcurrentBag ,所以你不想使用它。 它是一般LINQ框架的一部分,可以组合不可变序列。 当然,这个框架不会尝试将操作数的并发属性扩展到结果,因此生成的对象不太适合multithreading访问。

(基本上, Concat适用于ConcurrentBag因为它暴露了IEnumerable接口。)

(我知道这是一个老post,以为我会添加一些东西)。

像其他人一样说:是的,你需要逐个添加它们。 在我的情况下,我添加了一个小的扩展方法,使事情更清洁,但在引擎盖下它做同样的事情:

  public static void AddRange(this ConcurrentBag @this, IEnumerable toAdd) { foreach (var element in toAdd) { @this.Add(element); } } 

然后:

  ConcurrentBag ccBag = new ConcurrentBag(); var listOfThings = new List() { 1, 2, 4, 5, 6, 7, 8, 9 }; ccBag.AddRange(listOfThings); 

我还看了使用AsParallel在扩展方法中添加,但是在添加各种大小的字符串列表运行一些测试后,使用AsParallel(如此处所示)与传统的for循环相比,速度要慢得多。

  public static void AddRange(this ConcurrentBag @this, IEnumerable toAdd) { toAdd.AsParallel().ForAll(t => @this.Add(t)); } 

Concat是LINQ提供的扩展方法。 它是一个不可变的操作,它返回另一个IEnumerable ,它可以枚举源集合,紧接着是指定的集合。 它不会以任何方式更改源集合。

您需要一次将项目添加到ConcurrentBag

我遇到了类似的问题,尝试并行处理较小的数据块,因为一个大块超时我用来访问发送端数据的Web服务,但我不希望通过处理每个块来减慢运行速度连续。 按记录处理数据记录甚至更慢 – 因为我调用的服务可以处理批量请求,所以最好尽可能多地提交而不会超时。

就像弗拉德说的那样,将一个并发包连接到一个对象类型的列表不会返回一个并发包,所以concat将无法工作! (我花了一段时间才意识到我做不到。)

试试这个 – 创建一个List ,然后创建一个ConcurrentBag> 。 在每次并行迭代中,它将向并发包添加新列表。 完成并行循环后,循环遍历ConcurrentBag和concat(或者如果要消除可能重复的联合)到您创建的第一个List以将所有内容“展平”到一个列表中。