在Linq语句中使用ConcurrentQueue

时间:2011-09-09 23:27:24

标签: c# .net-4.0 concurrent-collections

如果我有一个ConcurrentQueue,是否有一种首选的方法来使用Linq语句?它没有将所有项目作为序列出列的方法,并且它的枚举器不会删除项目。

我正在进行批量消费,这意味着我会定期处理队列并清空它,而不是处理它直到它为空并阻塞直到更多项被入队。 BlockingCollection似乎不会起作用,因为当它到达最后一个项目时它会阻塞,我希望该线程做其他事情,比如清除其他队列。

static ConcurrentQueue<int> MyQueue = new ConcurrentQueue<int>();
void Main()
{
    MyQueue.Enqueue(1);MyQueue.Enqueue(2);MyQueue.Enqueue(3);MyQueue.Enqueue(4);MyQueue.Enqueue(5);

    var lst = MyQueue.ToLookup(x => x.SomeProperty);
    //queue still has all elements
    MyQueue.Dump("queue");  
}

目前,我已经制作了一个辅助方法

static IEnumerable<T> ReadAndEmptyQueue<T>(this ConcurrentQueue<T> q)
{
    T item;
    while(q.TryDequeue(out item))
    {
        yield return item;
    }
}

var lk = MyQueue.ReadAndEmptyQueue().ToLookup(x => x.SomeProperty);
MyQueue.Dump(); //size is now zero

有更好的方法,还是我做得对?

1 个答案:

答案 0 :(得分:3)

在我看来,你的方法非常合理。允许使用者以这种方式清空队列简洁明了。

  

BlockingCollection似乎不会起作用,因为当它到达最后一个项目时它会阻塞,我希望该线程做其他事情,比如清除其他队列。

我要提到的一件事 - 有时候,从设计的角度来看,每个队列触发一个单独的消费者线程更容易。如果你这样做,每个BlockingCollection<T>可以只使用GetConsumingEnumerable()并根据需要阻止,因为当队列为空时它们将处于等待状态。

这是我更频繁采用的方法,因为从同步的角度来看,如果每个集合都有一个或多个专用消费者,而不是消费者在消费者之间进行切换,那么这种方法通常要简单得多。