2011-04-30 68 views
12

我需要一个不允许重复的共同集合(在BlockingCollection中用作生产者/消费者)。 我不需要严格的元素顺序。 从另一方面,我想尽量减少元素“生活”收集的最大时间。即收集一定不能是LIFO,理想情况下它应该是FIFO。如何创建不重复的ConcurrentQueue?

那么我会说,我需要ConcurrentQueue没有重复允许,但ConcurrentBag没有重复也可以工作。

为什么C#不包含这样的东西,可能有人已经创建了它?

这个问题我刚才的问题的结果What type of IProducerConsumerCollection<T> to use for my task?

+5

C#只是一种语言,你必须寻找一个库来获得这样的功能。像.NET框架一样,ConcurrentQueue/Bag的主页。没有人考虑过这样写代码,它注定要失败。因为你无法准确预测生产者何时生产和消费者消费。确定何时消除重复数据大致类似于根据Random.Next()的返回值做出决定。无论什么原因你必须实现这样的事情:它注定要失败。 – 2011-05-01 00:01:19

+0

我不明白为什么它注定要失败。我可以使用ConcurrentDictionary来模拟Set(我将只使用key,value将始终为null)。我不想消除重复。应该没有重复。 – javapowered 2011-05-01 07:08:03

+0

此外,“坚果壳中的C#”指出可以编写并发堆栈:“但是,如果您编写了自己的并发集合以禁止重复,但是如果元素已经存在,则会使TryAdd返回false(例如,如果您写了并发集合)“ – javapowered 2011-05-01 09:13:11

回答

1

那么,如果你严格想有没有重复,你需要“设置”。例如NHibernate使用Iesi.Collections来提供这样的功能。以Iesi为例,您可以围绕提供的'Set'类(DictionarySet,HashSet,SortedSet)构建自己的功能。来源:http://www.codeproject.com/KB/recipes/sets.aspx

+1

.Net确实有一个'HashSet '。据我所知,NHibernate使用'Iesi.Collections'作为'ISet '(它在.Net库中没有好的选择)。 – svick 2011-05-01 00:42:28

+0

是的,新的.net 3.5及更高版本。 – 2011-05-01 00:43:51

3

没有内置的.Net库将这组规则集合在一起。你有三个选择:

  1. 写自己的集合类
  2. 使用两个集合:编写使用一个ConcurrentQueue和任何基于集收集的自定义类,自动检查重复;有添加到设置运行,如果成功,添加到ConcurrentQueue;每添加/删除将添加到这两个集合时成功
  3. 使用ConcurrentQueue但遍历整个列表检查重复

最后两个是不是很有效(一个内存,其他与CPU, I/O,锁定)并且由于需要显式锁定而变得混乱,但是会完成任务。他们会更快实施,但如果权衡不符合您的要求,您将不得不选择#1选项。

-3

您可以简单地使用ConcurrentQueue,并在致电Enqueue之前通过调用ConcurrentQueue.Contains<>方法来检查数据是否在队列中。我猜Contains<>扩展方法是相当不错的优化。

编辑: 正如其他人所指出的那样,这个工作将你必须使用一个锁定机制,如围绕Contains<>方法互斥等和Enqueue方法是这样的:

get mutex 
if not Contains<> 
{ 
    Enqueue 
} 
release mutex 
+3

我认为这是行不通的,因为竞态条件可能允许另一个线程在调用Contains和Enqueue之间入队一个“相等”的对象。我们真的需要一个ConcurrentSet <>来完成这项工作。 – ALEXintlsos 2012-06-01 21:32:27

+0

然后在关键代码周围添加一个互斥... – Chimera 2012-06-01 22:17:28

+2

...在这种情况下,您不需要并发版本的队列对象。我认为原始的海报正在寻找一种原子级防止重复的ConcurrentSet。 – ALEXintlsos 2012-06-04 15:26:13