是否有一个C#等价于Java';s BlockingQueue.drainTo(收集)方法?

是否有一个C#等价于Java';s BlockingQueue.drainTo(收集)方法?,c#,multithreading,queue,C#,Multithreading,Queue,我正在构建一个多线程C#应用程序,其中多个线程对队列中的元素作出贡献。单个线程正在使用同一队列上的元素。我希望单个线程对传入元素的元素进行一些缩减/合并,因此理想情况下,它会查看队列中的所有新元素,缩减它们,然后在缩减后处理条目。有点像这样: while (true) { Collection<Elem> elements = queue.TakeAll(); Collection<Elem> reducedElements = Reduce(elements);

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

while (true)
{
  Collection<Elem> elements = queue.TakeAll();
  Collection<Elem> reducedElements = Reduce(elements);
  for (Elem e in reducedElements)
  {
    process(e);
  }
}
System.Collections.Concurrent.ConcurrentQueue<string> loConcurrentQueue = new System.Collections.Concurrent.ConcurrentQueue<string>();

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

var loList = loConcurrentQueue.DrainTo();
while(true)
{
集合元素=queue.TakeAll();
集合减少元素=减少(元素);
对于(还原元素中的元素e)
{
过程(e);
}
}
但是显然没有任何TakeAll()方法。从Java的经验来看,我已经习惯了Java,它提供了一些我感兴趣的东西


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

看看命名空间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 poConcurrentQueue)
{
List loList=新列表();
T元素;
while(poConcurrentQueue.TryDequeue(out-loElement))
loList.Add(loElement);
返回列表;
}
}
然后像这样使用:

while (true)
{
  Collection<Elem> elements = queue.TakeAll();
  Collection<Elem> reducedElements = Reduce(elements);
  for (Elem e in reducedElements)
  {
    process(e);
  }
}
System.Collections.Concurrent.ConcurrentQueue<string> loConcurrentQueue = new System.Collections.Concurrent.ConcurrentQueue<string>();

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

var loList = loConcurrentQueue.DrainTo();
System.Collections.Concurrent.ConcurrentQueue loConcurrentQueue=new System.Collections.Concurrent.ConcurrentQueue();
loConcurrentQueue.Enqueue(“Element1”);
loConcurrentQueue.Enqueue(“Element2”);
var loList=loConcurrentQueue.DrainTo();

好的api设计不知道添加什么,而是知道不包含什么。一个TryDrainTo()和“此操作的行为未定义…”肯定使它很早就进入了剪切列表。线程安全是.NET风格中的一个主要设计目标,当您添加自己的(扩展)方法时,请不要忽略这一点。那么,它可能会提供类似的方法la TryTakeAll()或类似的方法。现在,我似乎没有办法在特定时间点原子地取出队列中的所有元素。从我开始提取元素的那一刻起,制作人可能会同时添加更多的元素。这并不能给你像德兰托那样的保证。也就是说,您以原子方式获取所有元素,这意味着发布服务器将被阻止添加更多元素,直到耗尽停止。如果没有这一保证,就有可能出现无限循环,因为发布繁忙,您永远无法到达队列的末尾。