Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/285.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 检查阻止集合中是否存在重复项_C#_.net - Fatal编程技术网

C# 检查阻止集合中是否存在重复项

C# 检查阻止集合中是否存在重复项,c#,.net,C#,.net,在尝试添加新项目之前,检查“blockingcollection”中是否存在项目的最佳方法是什么?基本上,我不想重复添加到BlockingCollection 使用TryAdd(数据)方法。您还可以传入一个timespan对象或int指示超时时间。返回true或false。 请注意,如果基础集合类型无法处理重复数据,并且您尝试添加的数据是重复数据,则会引发InvalidOperationException。您必须实现自己的IProducerConsumerCollection,其行为类似于集合(

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

使用
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;
  }
}