我遇到一个令人沮丧的问题,一直到深入浏览队列。我知道需要在打开选项中使用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
}
答案 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();
}