如何通过所有消息浏览Websphere MQ队列?

时间:2013-08-02 22:29:53

标签: c# ibm-mq

我遇到一个令人沮丧的问题,一直到深入浏览队列。我知道需要在打开选项中使用MQOO_BROWSE选项打开队列。然后在第一次读取时使用Get Messsage Option 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
}

3 个答案:

答案 0 :(得分:7)

这令人沮丧,但我能够依靠SO上发布的问题和答案来验证我是在正确的道路上。不幸的是,没有一个答案通过浏览解决了随后的GET问题,而且我很难过。在尝试了许多毫无结果的其他路径之后,我得到了答案,当我最终找到它时,它非常简单。我决定发布有效的Q&amp; A解决方案。

显然,一旦对MQMessage进行了GET,除非重新初始化它,否则GET无法获取下一条消息,并且会立即抛出MQRC_NO_MSG_AVAILABLE异常。在执行GET之前重新初始化MQMessage实例可以解决问题。我通过在while循环中的GET之前添加所需的代码行来修改上面的代码:

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

我做了这个更改后,例程浏览了队列中的所有消息。

答案 1 :(得分:4)

是的,这是正确的。每个MQMessage方法调用都需要Get的新实例。当Get方法返回消息时,MQMessage对象将使用从队列/主题检索的消息标题和消息正文进行初始化。例如,使用消息的消息ID初始化MessageId属性。

如果再次使用相同的对象来获取另一条消息,Get实际上会尝试获取之前检索到的消息MessageID的消息。由于队列中没有消息与给定的MessageID匹配,Get调用将返回2033 - MQRC_NO_MSG_AVAILABLE

答案 2 :(得分:4)

对于简单的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();
}