<分区>
在尝试添加新项目之前检查 BlockingCollection
中是否存在项目的最佳方法是什么?基本上我不想将重复项添加到 BlockingCollection
。
<分区>
在尝试添加新项目之前检查 BlockingCollection
中是否存在项目的最佳方法是什么?基本上我不想将重复项添加到 BlockingCollection
。
最佳答案
您必须实现自己的 IProducerConsumerCollection<T>
表现得像一个集合(例如,不允许重复)。这是一个使用关键部分 (C# lock
) 使其线程安全的简单版本。对于高并发场景,您可以使用类似 SpinWait
的类来提高性能与 ConcurrentQueue<T>
相同
public class ProducerConsumerSet<T> : IProducerConsumerCollection<T> {
readonly object gate = new object();
readonly Queue<T> queue = new Queue<T>();
readonly HashSet<T> hashSet = new HashSet<T>();
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<T> GetEnumerator() {
List<T> list = null;
lock (gate)
list = queue.ToList();
return list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
}
如果需要,您可以通过提供可选的 IEqualityComparer<T>
详细说明此类以自定义相等性然后用于初始化 HashSet<T>
.
IProducerConsumerCollection<T>.Add
方法返回 false
当试图插入重复项时。这导致 InvalidOperationException
由 BlockingCollection<T>.Add
抛出方法,因此您可能必须包装代码以将项目添加到如下所示的内容中:
bool AddItem<T>(BlockingCollection<T> blockingCollection, T item) {
try {
blockingCollection.Add(item);
return true;
}
catch (InvalidOperationException) {
return false;
}
}
请注意,如果您将项目添加到已完成的收藏中,您还将获得 InvalidOperationException
。并且您必须检查异常消息以确定异常的根本原因。
关于c# - 检查阻塞集合中的重复项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35745854/