2015-10-13 67 views
0

我从一个并行操作填充与CSV记录ConcurrentQueue(现在用我最好的收集选项?)包含ConcurrentQueue C#

ConcurrentQueue<string> bag = new ConcurrentQueue<string>(); 

"thisIsID123,they tossed an exception, error5678" 

我没有看到一个“包含”在此收集方法。我怎样才能通过收集查看女巫项目有“thisIsID123”?

+4

你看不到'Contains',因为它并没有真正使没有意义用于队列。也许你想要一个'HashSet '?你将在这些字符串上做什么操作? –

+0

ConcurrentQueue实现IEnumerable,那么包含LINQ扩展方法呢? –

+0

@Yuval我想从一个并行操作中填充一个集合。这样做很好。有更好的选择吗? – nlstack01

回答

2

你不能轻易做到这一点。你可以用一个队列来做的就是队列,出列或枚举。要在队列中查找元素,您需要用完整的迭代进行蛮力搜索。

foreach(var element in myQueue) 
{ 
    //... 
} 

...或与LINQ

也许更合适的容器可能有帮助吗? C5系列提供可在FIFO模式下运行的HashedLinkedList。它提供了链接列表(例如队列)和哈希表中最好的一个,以便快速访问队列中间的元素。它不是为并发使用而设计的,所以你必须使用锁来同步你的读写操作。快速nuget,你会在你的指尖。

不知道你的问题域太多,我觉得把每进入一个ConcurrentBag<T>ConcurrentQueue<T> (为什么?因为它是最有效的并发收集的插入,使极少数的假设有关预期使用) (见here对于每个并发采集的优点)以及在数据采集完成后处理采集的内容可能是优选的。你当然不需要队列提供的顺序,因为并行循环中的处理顺序无论如何都是不确定的,所以你将会以半随机顺序将元素放入集合中。

所以,在回答您的意见,您可以收集在一个袋子里的一切:

var bag=new ConcurrentBag<Tuple<int, string>>(); 
var random=new Random(); 
//lets create some tuples to put in our bag 
var objects = Enumerable 
        .Range(0, 1000000) 
        .Select(n= > Tuple.Create(n, n.ToString())) 
        .OrderBy(_ => random.Next()) 
        .ToList(); 
Parallel.ForEach(objects, obj=> 
{ 
    bag.Add(obj); 
}); 

然后进行查找出在包里的物品,使用特定属性作为键(这里我用元组的Item1属性):

var lookup = bag.ToLookup(x=>x.Item1); 

现在可以非常快速地查找其中的元组集合中有一个特定Item1值。

IEnumerable<Tuple<int,string>> itemsOfInterest = lookup[3]; 

因为可能有多个项目共享相同的属性值,所以返回enumerable。

如果你能保证你的输入数据有没有重复,而不是做一本字典:

var dic= bag.ToDictionary(x=>x.Item1); 

然后

var item = dic[3]; 
+0

我读了ConcurrentBag在队列上的性能问题http://ayende.com/blog/156097/the-high-cost-of-concurrentbag-in-net-4-0 – nlstack01

+0

@ nlstack01那篇文章是测量成本创建许多'ConcurrentBag '实例(并且问题似乎在.Net的更高版本中得到解决)。我建议你有一个单一的ConcurrentBag,放入你的元素。完全不同的命题。 – spender

+0

您是否介意在填充行李后,在Paralell.ForEach中显示填充行李的示例,然后根据上面的id获取元素? – nlstack01