5

我有一个 C# 4.0 应用程序,其“高优先级”和“低优先级”队列实现如下:

BlockingCollection highPriority = new BlockingCollection(1000); BlockingCollection lowPriority = new BlockingCollection(1000);

在 highPriority 中产生的任何数据都应该在 lowPriority 中产生的任何数据之前被使用。这里的转折是数据可以随时生成到两个队列中的任何一个。因此,在我使用 highPriority 中的所有数据之后,我将使用可能处于 lowPriority 的任何数据。如果在我以低优先级消费数据时,以高优先级产生新数据,我想以低优先级完成当前项目的消费,然后切换回并以高优先级处理数据。

任何人都可以建议一种算法来帮助解决这个问题吗?伪代码很好。非常感谢。

4

3 回答 3

3

这个怎么样:

while(true)
{
    workitem = highQueue.dequeue();

    if(workitem == null)
        workitem = lowQueueu.dequeue()

    process(workitem)
}
于 2011-04-01T17:14:06.130 回答
1

正如@Kevin Brock 建议的那样,如果可以的话,您将希望将其包装成一个对象,并让该对象实现IProducerConsumerCollection。否则,您的调用代码TryDequeue将执行繁忙的等待循环。也就是说,对于两个队列,您必须编写如下内容:

WorkItem item = null;
do
{
    if (!hpQueue.TryDequeue(out item))
    {
        lpQueue.TryDequeue(out item);
    }
while (item != null);

如果您使用自己的类,那么您可以使用事件(EventWaitHandle等)来防止忙等待。

事实上,使用优先级队列可能会更好。使优先级队列线程安全并实现 非常容易IProducerConsumerCollection,然后您可以将其与BlockingCollection. 一个好的起点是 Julian Bucknall在 C# 中的优先级队列

于 2011-04-01T18:18:07.797 回答
1

我会用一个优先级队列来做到这一点。这将允许您稍后添加第三个优先级,而代码更改很少。

我在使用 lockFree-SkipList 之前写过一个,但这里有一个使用普通跳过列表的项目 (http://www.codeproject.com/KB/recipes/PriorityQueueSkipList.aspx)。我使用了一个跳过列表,因为它们在并发下表现良好并且实现起来非常简单(减去无锁版本)。

我还在 CodePlex 上看到了一个使用红黑树的优先级队列,但我现在找不到它。更新:我正在考虑的优先队列实现是 NGenerics 项目的一部分:http ://code.google.com/p/ngenerics/

于 2011-04-02T19:59:00.440 回答