4

我在浏览队列时遇到了一个令人沮丧的问题。我知道队列需要使用打开选项中的 MQOO_BROWSE 选项打开。然后在第一次读取时使用获取消息选项 MQGMO_BROWSE_FIRST 执行 GET。最后,后续的 GET 应该使用 MQGMO_BROWSE_NEXT 选项。

问题是,我的尝试只能检索第一条消息!在第二次 GET 时,即使使用 MQGMO_BROWSE_NEXT,该方法也会抛出 MQRC_NO_MSG_AVAILABLE,即使队列中有 5 条消息!

这是我使用的代码:

IList<string> Messages = new List<string>();
_queueManager = new MQQueueManager(QueueManagerName);
int openOptions = MQC.MQOO_BROWSE  // open queue for browsing
_queue = QManager.AccessQueue(QueueName, openOptions);

MQGetMessageOptions mqGetMsgOpts = new MQGetMessageOptions();
mqGetMsgOpts.Options = MQC.MQGMO_BROWSE_FIRST;

MQMessage msg = new MQMessage();

_queue.Get(msg, mqGetMsgOpts);
MQGetMessageOptions mqGetNextMsgOpts = new MQGetMessageOptions();
mqGetNextMsgOpts.Options = MQC.MQGMO_BROWSE_NEXT;

try
{
    while (true)
    {
        string messageText = msg.ReadString(msg.MessageLength);
        Messages.Add(messageText);
        _queue.Get(msg, mqGetNextMsgOpts);
    }
}
catch (MQException ex)
{
    // Handle it
}
4

3 回答 3

12

This was frustrating, but I was able to rely upon questions and answers posted here on SO to verify that I was on the right path. Unfortunately, none of the answers addressed subsequent GETs with browse, and I was stumped. The answer came to me after trying a number of fruitless other paths, and it was very simple when I finally came to it. I decided to post the Q&A of my solution that worked.

Apparently, once having done a GET into an MQMessage, unless you re-initialize it, the GET can't get the next message, and it throws the MQRC_NO_MSG_AVAILABLE exception immediately. Re-initializing the MQMessage instance before performing the GET solves the problem. I modified the code above by adding the needed line of code just before the GET in the while loop:

while (true)
{
    string messageText = msg.ReadString(msg.MessageLength);
    Messages.Add(messageText);
    msg = new MQMessage();
    _queue.Get(msg, mqGetNextMsgOpts);
}

Once I made this change, the routine browsed all the messages on the queue.

于 2013-08-02T22:29:52.637 回答
6

Yes, that's correct. A new instance of MQMessage is required for every Get method call. When the Get method returns with a message, MQMessage object gets initialized with the message headers and body of the message retrieved from a queue/topic. For example the MessageId property gets initialized with message id of the message.

If the same object is used again to get another messages, the Get actually attempts to get a message that has MessageID of the message retrieved before. Since no message in the queue matches the given MessageID, the Get call returns with 2033 - MQRC_NO_MSG_AVAILABLE.

于 2013-08-03T13:54:47.583 回答
5

对于简单的 C# 程序,创建一个新的 MQMessage 对象很好,但对于将处理数千或数百万条消息的长时间运行的程序,这不是一个好方法。重用对象要好得多。

string messageText;
MQMessage msg = new MQMessage();
while (true)
{
    smessageText = msg.ReadString(msg.MessageLength);
    Messages.Add(messageText);
    _queue.Get(msg, mqGetNextMsgOpts);
    // Clear both MsgID and CorrelID for next use.
    msg.MessageId = MQC.MQMI_NONE;
    msg.CorrelationId = MQC.MQCI_NONE;
    // Optional, remove data from the message
    msg.ClearMessage();
}
于 2013-08-13T23:09:05.077 回答