【问题标题】:Can I peek into empty MSMQ without getting exception?我可以在没有异常的情况下查看空的 MSMQ 吗?
【发布时间】:2010-11-29 03:42:35
【问题描述】:

据我从文档中可以看出,您应该检查消息队列中是否有消息的方法是使用 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;
    }

我一直被告知 - 并且经历过 - 例外是昂贵的,不应该用于正常操作。所以我的问题是:

  • 我认为依靠捕获 MessageQueueException 是一项代价高昂的操作的假设是否正确?

  • 有什么方法可以同步检查队列中是否有消息而不必依赖异常?

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

【问题讨论】:

    标签: msmq


    【解决方案1】:
    • 是的,您认为异常代价高昂是正确的。实际上,昂贵的是投掷,而不是接球。队列有时为空是正常的,正常状态不应导致抛出异常。

    • 通过使用 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 可以更多地用于处理消息而不是处理抛出。

    【讨论】:

      【解决方案2】:

      试试 mq.GetAllMessages().Length> 0

      【讨论】:

      • 真的吗?即使您的队列可能包含 1000 条或 10.000 条大消息?这就像把整个超市都吃光了,只是因为你想知道他们是否还有苹果。
      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

        更新前:

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

        【讨论】:

        • 我们通过服务管道传递消息,我们在它们之间使用队列。我们希望获得尽可能高的吞吐量,所以这并非不重要,但到目前为止我们的性能已经足够好。
        • 我会等着看我是否有任何其他的 cmets,但如果我没有,我会接受你的回答:|
        猜你喜欢
        • 2016-10-12
        • 2019-10-27
        • 1970-01-01
        • 2020-03-26
        • 1970-01-01
        • 1970-01-01
        • 2020-08-12
        • 2017-12-31
        • 2019-01-31
        相关资源
        最近更新 更多