用于两个队列的.NET使用者线程处理的算法(基于优先级)

时间:2011-04-01 16:56:43

标签: .net algorithm queue producer-consumer

我有一个C#4.0应用程序,其中包含“高优先级”和“低优先级”队列:

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

在lowPriority中生成的任何数据之前,应先消耗highPriority中生成的任何数据。这里的扭曲是可以随时向两个队列中的任何一个生成数据。因此,在我消耗了highPriority中的所有数据之后,我将使用可能位于lowPriority中的任何数据。如果在我使用lowPriority中的数据时在highPriority中生成新数据,我想完成使用lowPriority中的当前项,然后切换回并处理highPriority中的数据。

有人建议使用算法来帮助解决这个问题吗?伪代码很好。非常感谢。

3 个答案:

答案 0 :(得分:3)

这个怎么样:

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

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

    process(workitem)
}

答案 1 :(得分: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的Priority Queue in C#

答案 2 :(得分:1)

我会用一个优先级队列来做这件事。这将允许您稍后添加第三优先级,只需很少的代码更改。

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

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