MSMQ получает тайм-ауты из .NET

#.net #msmq #message-queue

#.net #msmq #очередь сообщений

Вопрос:

Я хочу иметь возможность читать и обрабатывать сообщения из MSMQ. Очереди являются транзакционными. В настоящее время я использую этот код:

 while (true)
{
    using (var txn = new MessageQueueTransaction())
    {
        txn.Begin();

        try
        {
            var message = queue.Receive(txn);
            Dispatch(message);

            txn.Commit();
        }
        catch (MessageQueueException ex)
        {
            txn.Abort();
        }
    }
}
  

Где queue это System.Messaging.MessageQueue .

Я хотел бы использовать цикл while (!cancelled) , что означало бы вызов queue.Receive той перегрузки, которая принимает тайм-аут. Однако код выдает ошибку при достижении тайм-аута, и выдача такого количества исключений не может быть хорошей вещью. Существует ли TryRecieve , похожий на Monitor.TryEnter ? Peek кажется самым близким, но он также запускается при достижении тайм-аута.

Если я хочу чтение с высокой пропускной способностью из очереди и поддержку отмены, каков наилучший способ чтения из очереди?

Комментарии:

1. «выдача такого количества исключений не может быть хорошей вещью». Почему бы и нет? Вы их улавливаете. Не похоже, что что-то изнашивается 🙂 Одним из преимуществ использования тайм-аута является то, что вы не можете попасть в ситуацию ошибки, когда получение никогда не завершается. По истечении тайм-аута прием будет регулярно завершаться и вызываться снова.

2. Исключения не должны создаваться в неисключительных обстоятельствах (пустая очередь не является исключительной) — их создание обходится дорого, и помимо прочего, в GC добавляются дополнительные объекты для сбора.

3. Справедливые баллы. Однако пустая очередь не является исключением — это тайм-аут.

Ответ №1:

Используйте MessageQueue.Вместо этого BeginPeek(). Обработчик событий, который вы пишете для события PeekCompleted, запустится, как только будет доступно сообщение. Вы можете вызвать Receive() и быть уверенным, что получите сообщение без тайм-аута. В статье о библиотеке MSDN есть хороший пример.

Ответ №2:

Это не прямой ответ, но я бы использовал протокол net.msmq в WCF для обработки моего messageQ. Это аккуратный простой подход, который может удовлетворить все сценарии, которые вы упомянули здесь.