3

如果我有一个 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

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

4

1 回答 1

3

在我看来,您的方法非常合理。允许消费者以这种方式清空队列既干净又简单。

BlockingCollection 似乎不会起作用,因为它会在到达最后一项时阻塞,我希望该线程执行其他操作,例如清除其他队列。

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

这是我更经常采用的方法,因为从同步的角度来看,如果每个集合都有一个或多个专用消费者,而不是消费者在它所消费的内容之间切换,它通常会简单得多。

于 2011-09-09T23:36:45.083 回答