Bob*_*orn 35 c# concurrency concurrent-collections
有没有办法一次向ConcurrentBag添加多个项目,而不是一次添加一个?我没有在ConcurrentBag上看到AddRange()方法,但是有一个Concat().但是,这对我不起作用:
ConcurrentBag<T> objectList = new ConcurrentBag<T>();
timeChunks.ForEach(timeChunk =>
{
List<T> newList = Foo.SomeMethod<T>(x => x.SomeReadTime > timeChunk.StartTime);
objectList.Concat<T>(newList);
});
Run Code Online (Sandbox Code Playgroud)
这段代码曾经在Parallel.ForEach()中,但我把它改成了上面所以我可以解决它.变量newList确实有对象,但是在objectList.Concat <>行之后,objectList总是有0个对象.Concat <>不能那样工作吗?我是否需要使用Add()方法一次一个地向ConcurrentBag添加项目?
小智 35
(我知道这是一个老帖子,以为我会添加一些东西).
像其他人一样说:是的,你需要逐个添加它们.在我的情况下,我添加了一个小的扩展方法,使事情更清洁,但在引擎盖下它做同样的事情:
public static void AddRange<T>(this ConcurrentBag<T> @this, IEnumerable<T> toAdd)
{
foreach (var element in toAdd)
{
@this.Add(element);
}
}
Run Code Online (Sandbox Code Playgroud)
然后:
ConcurrentBag<int> ccBag = new ConcurrentBag<int>();
var listOfThings = new List<int>() { 1, 2, 4, 5, 6, 7, 8, 9 };
ccBag.AddRange(listOfThings);
Run Code Online (Sandbox Code Playgroud)
我还看了使用AsParallel在扩展方法中添加,但是在添加各种大小的字符串列表运行一些测试之后,使用AsParallel(如此处所示)与传统的for循环相比,速度慢得多.
public static void AddRange<T>(this ConcurrentBag<T> @this, IEnumerable<T> toAdd)
{
toAdd.AsParallel().ForAll(t => @this.Add(t));
}
Run Code Online (Sandbox Code Playgroud)
Bri*_*eon 19
Concat是LINQ提供的扩展方法.这是一个不可变的操作,它返回另一个IEnumerable可以枚举源集合,紧接着是指定集合的操作.它不会以任何方式更改源集合.
您需要一次添加ConcurrentBag一个项目.
小智 6
我遇到了类似的问题,试图并行处理较小的数据块,因为一个大块超时我用来访问发送端数据的Web服务,但我不希望通过处理每个块来减慢运行速度连续.按记录处理数据记录甚至更慢 - 因为我调用的服务可以处理批量请求,所以最好尽可能多地提交而不超时.
就像弗拉德说的那样,将一个并发包连接到一个对象类型的列表不会返回一个并发包,所以concat将不起作用!(我花了一段时间才意识到我做不到.)
试试这个 - 创建一个List<T>,然后创建一个ConcurrentBag<List<T>>.在每次并行迭代中,它将向并发包添加新列表.完成并行循环后,循环遍历ConcurrentBag和concat(或者如果要消除可能的重复项,则为union)到List<T>您创建的第一个"将所有内容""展平"到一个列表中.
是的:)
Concat也许是其中一个Enumerable扩展.它没有添加任何内容ConcurrentBag,只是返回一些包含原始包的时髦对象以及您尝试添加的任何内容.
要注意的是结果Concat不是ConcurrentBag了,所以你不希望使用它.它是一般LINQ框架的一部分,可以组合不可变序列.当然,这个框架不会尝试将操作数的并发属性扩展到结果,因此生成的对象不太适合多线程访问.
(基本上Concat适用于ConcurrentBag因为它暴露了IEnumerable<T>接口.)
| 归档时间: |
|
| 查看次数: |
22053 次 |
| 最近记录: |