我知道你不应该在非特殊情况下使用例外,但是我想要通过其他人来看看我想做的事情是不是真的那么糟糕。
我有一个试图从MSMQ消息队列中获取消息的例程。如果队列中没有可用消息,它将检查辅助源以查看该消息是否可用。例程如下:
void CheckForMessages(out Message msg, TimeSpan timeout)
{
try
{
queue.Peek(timeout);
}
catch(MessageQueueException ex)
{
if (e.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout)
{
if (messageAvailable)
{
msg = SecondaryMessageSource();
}
}
throw;
}
msg = queue.Receive();
}
MSMQ没有提供检查队列中消息计数的机制。确定消息是否可用的唯一方法是使用Peek。如果发生MessageQueueException并将其错误设置为IOTimeout,则Peek已超时且队列中没有可用消息。
此例程将在线程的循环内调用,该线程的唯一目的是检索消息。超时将在毫秒范围内。调用堆栈由单个方法组成,并且线程负责不执行任何其他操作。我知道该方法将不断抛出异常,这被认为是不好的做法,但在这种情况下它真的那么糟糕吗?如果是这样,是否有人对如何完成此任务有任何建议,而代码不会完全错综复杂?
答案 0 :(得分:2)
由于你的程序逻辑(检查一个队列,如果没有消息,检查另一个),并且由于MSMQ的工作方式,你将不得不处理异常。但是,我觉得有可能比在catch子句中使用该代码更优雅。
这就是我要做的事情:
private const int ReceiveTimeout = xxxx;
private bool TryReceiveMessage(MessageQueue queue, out Message message)
{
try
{
message = queue.Receive(ReceiveTimeout);
// if we made it here, we are good and have a message
return true;
}
catch(MessageQueueException ex)
{
if (MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout)
{
// this is not exceptional to us, so just return false
return false;
}
// Throw anything else as it is unexpected
throw;
}
}
然后,我会将您的调用方法编码为:
private Message MyMethodThatIsCalledInALoop()
{
// These could also be params, etc.
MessageQueue primary = // whatever code to get a reference to your primary queue
MessageQueue secondary = // whatever code to get a reference to your secondary queue
Message message = null;
if (TryReceiveMessage(primary, out message))
{
return message;
}
if (TryReceiveMessage(secondary, out message))
{
return message;
}
// this would still be null
return message;
}
答案 1 :(得分:0)
MSMQ没有提供检查队列中消息计数的机制。确定消息是否可用的唯一方法是使用Peek。如果发生MessageQueueException并将其错误设置为IOTimeout,则Peek已超时并且队列中没有可用消息
你自己回答了。由于没有别的办法,你有什么选择?
答案 2 :(得分:0)
您应该为每个轮询作业创建2个单独的线程,并让它们将消息存储在同步队列中,以便主线程可以对它们进行排序并从中获取适当的线程。这样,您就可以在Peek
来电中设置“无限”超时。