.NET асинхронный MSMQ

Я не понимаю, где что-то не так. По сути, у меня есть программа, которая получает из очереди сообщений и обрабатывает сообщения. Программа может быть остановлена ​​в любой момент, и в этом случае цикл обработки сообщений завершит свою работу до выхода из программы. Я пытаюсь выполнить это с помощью следующего кода:

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. Сообщение (или 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;
        }
    }
}
5
задан Barguast 30 March 2011 в 14:56
поделиться