如果我有一个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
有更好的方法,还是我做得对?
答案 0 :(得分:3)
在我看来,你的方法非常合理。允许使用者以这种方式清空队列简洁明了。
BlockingCollection似乎不会起作用,因为当它到达最后一个项目时它会阻塞,我希望该线程做其他事情,比如清除其他队列。
我要提到的一件事 - 有时候,从设计的角度来看,每个队列触发一个单独的消费者线程更容易。如果你这样做,每个BlockingCollection<T>
可以只使用GetConsumingEnumerable()
并根据需要阻止,因为当队列为空时它们将处于等待状态。
这是我更频繁采用的方法,因为从同步的角度来看,如果每个集合都有一个或多个专用消费者,而不是消费者在消费者之间进行切换,那么这种方法通常要简单得多。