我不明白哪里出了问题。基本上,我有一个从消息队列接收并处理消息的程序。程序可以在任何时候停止,在这种情况下,消息循环在程序退出之前完成了它正在做的事情。我试着用下面的代码来实现这一点:
private MessageQueue q;
private ManualResetEventSlim idle;
public void Start()
{
idle = new ManualResetEventSlim();
q.ReceiveCompleted += this.MessageQueue_ReceiveCompleted;
q.BeginReceive();
}
public void Stop()
{
this.q.Dispose();
this.idle.Wait();
}
private void MessageQueue_ReceiveCompleted(object sender,
ReceiveCompletedEventArgs e)
{
Message inMsg;
try
{
inMsg = e.Message;
}
catch (Exception ex)
{
this.idle.Set();
return;
}
// Handle message
this.q.BeginReceive();
}很显然,Stop方法将清除消息队列,然后等待设置空闲等待句柄(这应该发生在释放时将调用ReceiveCompleted事件,但e.Message属性应该除外)。
但是,消息循环仍在继续!我已经释放了消息队列,但它仍然设法从消息队列中读取数据,并且不会调用异常处理程序,这意味着idle.Wait行将永远等待。
我的理解是,处理消息队列应该结束所有挂起的接收并调用事件,但是e.Message (或q.EndReceive)应该抛出异常。难道不是这样吗?如果没有,我还能如何安全地退出消息循环?
谢谢
更新:
下面是一个完整的示例(假设队列存在)
class Program
{
static MessageQueue mq;
static ManualResetEventSlim idleWH;
static void Main(string[] args)
{
idleWH = new ManualResetEventSlim();
Console.WriteLine("Opening...");
using (mq = new MessageQueue(@".\private$\test"))
{
mq.Formatter = new XmlMessageFormatter(new Type[] { typeof(int) });
mq.ReceiveCompleted += mq_ReceiveCompleted;
for (int i = 0; i < 10000; ++i)
mq.Send(i);
Console.WriteLine("Begin Receive...");
mq.BeginReceive();
Console.WriteLine("Press ENTER to exit loop");
Console.ReadLine();
Console.WriteLine("Closing...");
mq.Close();
}
Console.WriteLine("Waiting...");
idleWH.Wait();
Console.WriteLine("Press ENTER (ex)");
//Console.ReadLine();
}
static void mq_ReceiveCompleted(object sender, ReceiveCompletedEventArgs e)
{
try
{
var msg = mq.EndReceive(e.AsyncResult);
Console.Title = msg.Body.ToString();
// Receive next message
mq.BeginReceive();
}
catch (Exception ex)
{
idleWH.Set();
return;
}
}
}发布于 2013-03-11 21:11:44
我能让它工作的唯一方法是使用事务性队列。任何非事务性队列似乎都容易受到此问题的影响。不是一个答案,但我能给任何找到这个的人最好的建议。
发布于 2011-03-30 21:05:27
我根本不知道你是怎么做到的。您必须在该事件中调用MessageQueue.EndReceive()。只有该方法才能抛出异常。查看ReceiveCompleted事件的MSDN示例代码。并且不要捕获异常,这只会导致无法诊断的故障。捕获在处理队列时获得的特定异常ObjectDisposedException。
发布于 2012-05-03 20:34:23
private static volatile bool _shouldStop = false;。。。
_shouldStop = true;
mq.Close();。。。
try
{
var msg = mq.EndReceive(e.AsyncResult);
if ( _shouldStop)
{
idleWH.Set();
return;
}
mq.BeginReceive();
}。。。
https://stackoverflow.com/questions/5486058
复制相似问题