C# 检查阻止集合中是否存在重复项
在尝试添加新项目之前,检查“blockingcollection”中是否存在项目的最佳方法是什么?基本上,我不想重复添加到BlockingCollection 使用C# 检查阻止集合中是否存在重复项,c#,.net,C#,.net,在尝试添加新项目之前,检查“blockingcollection”中是否存在项目的最佳方法是什么?基本上,我不想重复添加到BlockingCollection 使用TryAdd(数据)方法。您还可以传入一个timespan对象或int指示超时时间。返回true或false。 请注意,如果基础集合类型无法处理重复数据,并且您尝试添加的数据是重复数据,则会引发InvalidOperationException。您必须实现自己的IProducerConsumerCollection,其行为类似于集合(
TryAdd(数据)
方法。您还可以传入一个timespan
对象或int
指示超时时间。返回true
或false
。
请注意,如果基础集合类型无法处理重复数据,并且您尝试添加的数据是重复数据,则会引发
InvalidOperationException
。您必须实现自己的IProducerConsumerCollection
,其行为类似于集合(例如,不允许重复)。这里是一个简单的版本,它使用了一个关键部分(C#锁
)来保证线程安全。对于高并发性场景,您可以使用类似于SpinWait
的类来提高性能,方法与ConcurrentQueue
相同
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();
}
}
请注意,如果向已完成的集合添加项目,您还将获得一个
InvalidOperationException
,您必须检查异常消息以确定异常的根本原因。所有基础(IProdCons)类都接受重复项,因此,我认为这本身不会有帮助。我发现这种方法存在一个问题,如果生产者添加了重复项,导致InvalidOperationException,则阻塞集合不会达到上限
bool AddItem<T>(BlockingCollection<T> blockingCollection, T item) {
try {
blockingCollection.Add(item);
return true;
}
catch (InvalidOperationException) {
return false;
}
}