是否有一个C#等同于Java的BlockingQueue.drainTo(Collection)方法?

时间:2017-02-03 04:58:52

标签: c# multithreading queue

我正在构建一个多线程C#应用程序,其中多个线程对队列中的元素有贡献。单个线程正在消耗同一队列上的元素。我希望单个线程对传入元素的元素进行一些缩减/合并,理想情况下,它会查看队列中的所有新元素,减少它们,然后在缩小后处理条目。有点像这样:

while (true)
{
  Collection<Elem> elements = queue.TakeAll();
  Collection<Elem> reducedElements = Reduce(elements);
  for (Elem e in reducedElements)
  {
    process(e);
  }
}

但显然没有任何TakeAll()方法。从Java经验来看,我已经习惯了BlockingQueue's drainTo method,它提供了我感兴趣的东西。

我可以通过使用TryTake自己实现一些东西,直到队列为空。但这样做的风险在于,生产线程可能也会忙于生成,这将导致集合没有有限的结束来减少和处理。我基本上都在寻找一种方法,将所有内容从队列中取出,将其留空但提供可以处理的集合。

1 个答案:

答案 0 :(得分:0)

查看名称空间System.Collections.Concurrent中的ConcurrentQueue

此队列用于线程安全操作。

您可以轻松添加扩展方法用于您的目的。

public static class Extensions
{
    public static List<T> DrainTo<T>(this System.Collections.Concurrent.ConcurrentQueue<T> poConcurrentQueue)
    {
        List<T> loList = new List<T>();
        T loElement;
        while (poConcurrentQueue.TryDequeue(out loElement))
            loList.Add(loElement);
        return loList;
    }
}

并使用如下:

System.Collections.Concurrent.ConcurrentQueue<string> loConcurrentQueue = new System.Collections.Concurrent.ConcurrentQueue<string>();

loConcurrentQueue.Enqueue("Element1");
loConcurrentQueue.Enqueue("Element2");

var loList = loConcurrentQueue.DrainTo();