检查阻止集合中的重复项

在尝试添加新项目之前,检查某个项目是否存在于“blockingcollection”中的最佳方法是什么? 基本上我不想将重复项添加到BlockingCollection中。

您必须实现自己的IProducerConsumerCollection ,其行为类似于一个集合(例如,不允许重复)。 这是一个简单的版本,它使用一个关键部分(C# lock )来使其成为线程安全的。 对于高并发场景,您可以通过使用类似SpinWait的类来提高性能,方法与ConcurrentQueue相同。

 public class ProducerConsumerSet : IProducerConsumerCollection { readonly object gate = new object(); readonly Queue queue = new Queue(); readonly HashSet hashSet = new HashSet(); public void CopyTo(T[] array, int index) { if (array == null) throw new ArgumentNullException("array"); if (index < 0) throw new ArgumentOutOfRangeException("index"); lock (gate) queue.CopyTo(array, index); } public bool TryAdd(T item) { lock (gate) { if (hashSet.Contains(item)) return false; queue.Enqueue(item); hashSet.Add(item); return true; } } public bool TryTake(out T item) { lock (gate) { if (queue.Count == 0) { item = default(T); return false; } item = queue.Dequeue(); hashSet.Remove(item); return true; } } public T[] ToArray() { lock (gate) return queue.ToArray(); } public void CopyTo(Array array, int index) { if (array == null) throw new ArgumentNullException("array"); lock (gate) ((ICollection) queue).CopyTo(array, index); } public int Count { get { return queue.Count; } } public object SyncRoot { get { return gate; } } public bool IsSynchronized { get { return true; } } public IEnumerator GetEnumerator() { List list = null; lock (gate) list = queue.ToList(); return list.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } 

如果需要,您可以通过提供可选的IEqualityComparer来详细说明此类以自定义相等性,然后将其用于初始化HashSet

当尝试插入重复项时, IProducerConsumerCollection.Add方法返回false 。 这会导致BlockingCollection.Add方法抛出InvalidOperationException ,因此您可能需要包装代码以将项添加到以下内容中:

 bool AddItem(BlockingCollection blockingCollection, T item) { try { blockingCollection.Add(item); return true; } catch (InvalidOperationException) { return false; } } 

请注意,如果将项添加到已完成的集合中,您还将获得InvalidOperationException并且必须检查exception消息以确定exception的根本原因。

使用TryAdd(data)方法。 您还可以传入timespan对象或int指示超时时间。 返回truefalse 。 请注意,如果底层集合类型无法处理重复项,并且您尝试添加的数据是重复的,则会引发InvalidOperationException