Pregunta

No entiendo dónde va esto equivocado. Básicamente, tengo un programa que recibe de una cola de mensajes y procesa los mensajes. El programa se puede detener en cualquier momento, en cuyo caso el bucle de mensaje terminó lo que está haciendo antes de que salga el programa. Estoy tratando de lograr esto con el siguiente código:

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

Como es, lo que es aparente, el método de parada dispone de la cola de mensajes, y luego espera que se configure la manija de espera inactiva (que debe ocurrir a medida que se llame a un evento receptomontado cuando se deseche, pero la propiedad E.Message debería excepto ).

Sin embargo, el bucle de mensaje solo continúa! He dispuesto la cola de mensajes, pero aún así logra leerla y el controlador de excepciones no se invoca, lo que significa que la línea inactiva. "La línea espera para siempre.

Mi comprensión es que la disposición de una cola de mensajes debería terminar cualquier pendiente recibe e invoque el evento, pero el e.Message (o Q.endreceive) debe lanzar una excepción. ¿Este no es el caso? Si no, ¿de qué otra manera puedo salir de forma segura mi bucle de mensaje?

gracias

Actualización:

Aquí hay un ejemplo completo (asume que existe la cola)

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;
        }
    }
}

¿Fue útil?

Solución 2

La única forma en que podría obtener este trabajo fue con una cola transaccional.Cualquier cola no transaccional parece ser vulnerable a esto.No es una respuesta, pero el mejor consejo que puedo dar a cualquiera que encuentre esto.

Otros consejos

No estoy seguro de cómo hiciste este trabajo en absoluto.Usted debe llamar MessageQueue.endReceive () en el evento.Sólo ese método puede lanzar la excepción.Revise el código de muestra MSDN para el evento RecibreCompleted.Y no atrape la excepción, eso solo causa un fracaso no diagnosticado.Coge la excepción específica que obtiene cuando desechas la cola, el objetoDisposiciónException.

    private static volatile bool _shouldStop = false;

...

            _shouldStop = true;
            mq.Close();

...

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

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

            mq.BeginReceive();
        }

...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top