我可以偷看空MSMQ而不会出现异常吗?

时间:2009-09-17 13:07:18

标签: msmq

据我在文档中看到,您应该检查消息队列中是否有消息的方式是使用Peek方法。然后,您依靠它失败并返回MessageQueueException来告诉您队列为空。

    public bool IsQueueEmpty()
    {
        bool isQueueEmpty = false;
        MessageQueue myQueue = new MessageQueue(".\\myQueue");

        try
        {
            myQueue.Peek(new TimeSpan(0));
            isQueueEmpty = false;
        }

        catch(MessageQueueException e)
        {
            if (e.MessageQueueErrorCode == 
                MessageQueueErrorCode.IOTimeout)
            {
                isQueueEmpty = true;
            }
        }
        return isQueueEmpty;
    }

我总是被告知 - 并且经历过 - Exeptions价格昂贵,不应该用于正常操作。所以我的问题是:

  • 我依赖捕获MessageQueueException的假设是否是一项代价高昂的操作?

  • 有没有办法同步检查队列中是否有消息而不必依赖异常?

我正在使用C#中的System.Messaging命名空间,但如果我需要不受管理来解决这个问题,那么这可能是一个选项。请注意,我想要一个不使用带有MSMQ的WCF的解决方案。

4 个答案:

答案 0 :(得分:12)

  • 是的,你认为异常代价高昂是正确的。实际上这是投掷是昂贵的,而不是捕捉。队列有时是空的是正常的,正常状态不应该导致抛出异常。

  • 通过使用MessageQueue.GetMessageEnumerator2,我们可以使用枚举器来确定队列是否为空而不加载所有消息。使用这种方法,我们永远不会加载多条消息。

示例:

private static bool IsQueueEmpty(MessageQueue queue)
{
    using (var enumerator = queue.GetMessageEnumerator2())
    {
        return !enumerator.MoveNext();
    }
}

或实现Peek,如果消息队列为空(未经测试但应该有效),则返回null

private static Message Peek(MessageQueue queue)
{
    using (var enumerator = queue.GetMessageEnumerator2())
    {
        return enumerator.MoveNext() ? enumerator.Current : null;
    }
}

我们使用原始代码来检查大约20个不同的队列。由于我们从原始实现更改为我建议的实现,因此我们的导入速度急剧增加,因为CPU可以更多地用于处理消息而不是处理抛出。

答案 1 :(得分:1)

更新:我并不认为性能不重要。但我认为与异常相比,进程间通信非常昂贵。

更新前:

  • 我认为在进程间通信(这是msmq所做的)的上下文中,异常的成本并不重要。测试你是否想要确定。
  • 我不这么认为。

答案 2 :(得分:-1)

MSMQ不是完全进程间通信。进程间通信主要在单机中,但msmq可用于不同的计算机通信。保证交付,与在相同的操作系统中相反。

答案 3 :(得分:-2)

如何尝试mq.GetAllMessages()。长度> 0