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

Tor*_*ørn 6 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;
    }
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

Osk*_*erg 12

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

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

例:

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

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

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

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


Iga*_*ban 1

更新:我并不是说性能不重要。但我认为与异常相比,进程间通信的成本非常高。

更新前:

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