Алгоритм обработки потребительских потоков .NET двух очередей (в зависимости от приоритета) - PullRequest
5 голосов
/ 01 апреля 2011

У меня есть приложение на C # 4.0 с очередями «высокий приоритет» и «низкий приоритет», реализованными так:

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

Любые данные, созданные в highPriority, должны быть использованы до того, как любые данные будут получены в lowPriority.Суть в том, что данные могут быть переданы в любую из двух очередей в любое время.Поэтому после того, как я использовал все данные в highPriority, я буду использовать любые данные, которые могут находиться в lowPriority.Если новые данные создаются в highPriority, а я использую данные в lowPriority, я хочу закончить потребление текущего элемента в lowPriority, а затем переключиться назад и обработать данные в highPriority.

Может кто-нибудь предложить алгоритм, который поможетс этим?Псевдокод в порядке.Большое спасибо.

Ответы [ 3 ]

3 голосов
/ 01 апреля 2011

Как насчет этого:

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

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

    process(workitem)
}
1 голос
/ 02 апреля 2011

Я бы сделал это с одной приоритетной очередью. Это позволит вам добавить третий приоритет позже, с очень небольшим изменением кода.

Я написал один, прежде чем использовать lockFree-SkipList, но вот проект для одного, который использует обычный список пропусков (http://www.codeproject.com/KB/recipes/PriorityQueueSkipList.aspx). Я использовал список пропусков, потому что они хорошо формируются при параллельности и довольно просты в реализации (без версии без блокировки).

Я также видел приоритетную очередь в CodePlex, где используется красно-черное дерево, но сейчас я не могу его найти. ОБНОВЛЕНИЕ: Реализация приоритетной очереди, о которой я думал, была частью проекта NGenerics: http://code.google.com/p/ngenerics/

1 голос
/ 01 апреля 2011

Вы можете обернуть это в один объект, если можете, как предложил @Kevin Brock, и заставить этот объект реализовать IProducerConsumerCollection.В противном случае ваш код, который вызывает TryDequeue, будет выполнять занятый цикл ожидания.То есть с двумя очередями вы должны написать что-то вроде:

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

Если вы используете свой собственный класс, то вы можете использовать события (EventWaitHandle и т. Д.), Чтобы предотвратить ожидание занятости.

По правде говоря, вам, вероятно, будет лучше использовать очередь с приоритетами.Было бы довольно просто сделать приоритетную очередь потокобезопасной и реализовать IProducerConsumerCollection, а затем вы можете использовать ее с BlockingCollection.Хорошее место для начала - очередь приоритетов Джулиана Бакнола в C # .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...