我不明白这是错的。基本上,我有一个程序从消息队列接收并处理消息。程序可以随时停止,在这种情况下,消息循环完成了在程序退出之前正在进行的内容。我正在尝试使用以下代码来完成此操作:

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();
}
.

如希望明显,停止方法分类消息队列,然后等待要设置的空闲等待句柄(哪个应该在被调用时调用,但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;
        }
    }
}
.

有帮助吗?

解决方案 2

我可以获得这项工作的唯一方法是使用事务队列。任何非事务队列都似乎很容易受到影响。不是一个答案,但我能给任何人都能找到这个的最好的建议。

其他提示

并不完全确定如何使这项工作。在事件中,您必须呼叫messagequeue.endreceive()。只有那种方法可以抛出异常。查看接收完整事件的MSDN示例代码。并且不要抓住异常,这只是导致无法核不起的失败。捕获在处理队列时,ObjectDisposedException的特定异常。

    private static volatile bool _shouldStop = false;
.

。。。

            _shouldStop = true;
            mq.Close();
.

。。。

        try
        {
            var msg = mq.EndReceive(e.AsyncResult);

            if ( _shouldStop)
            {
                idleWH.Set();
                return;
            }

            mq.BeginReceive();
        }
.

。。。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top