Pergunta

Eu não entendo onde isso vai dar errado.Basicamente, eu tenho um programa que recebe a partir de uma fila de mensagem e processa as mensagens.O programa pode ser interrompido a qualquer momento, caso em que o loop de mensagem de terminar o que está fazendo antes de sair do programa.Eu estou tentando fazer isso com o seguinte 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 é espero que aparente, o método Stop descarta a mensagem da fila e, em seguida, aguarda o ocioso esperar identificador para ser definido (o que deve ocorrer como um ReceiveCompleted evento será chamado quando descartados, mas o endereço de e.Mensagem de propriedade deve exceto).

No entanto, o loop de mensagem apenas continua!!!Eu tenho dispostos a fila de mensagens, mas, ainda assim, consegue ler e o manipulador de exceção não é invocada, ou seja, o ocioso.Aguarde linha de espera para sempre.

Meu entendimento é que eliminar uma fila de mensagens DEVE terminar qualquer curso recebe e invocar o evento, mas os endereços de e.Mensagem (ou q.EndReceive) deve lançar uma exceção.Este não é o caso?Se não, de que outra forma posso sair em segurança o meu ciclo de mensagem?

Obrigado

ATUALIZAÇÃO:

Aqui está um exemplo completo (assume a fila existe)

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;
        }
    }
}
Foi útil?

Solução 2

A única maneira que eu poderia começar este trabalho, com uma fila transacional.Qualquer não-transacional fila parece estar vulnerável a este.Não uma resposta, mas o melhor conselho que posso dar a qualquer pessoa que encontrar este.

Outras dicas

Não sei como você fez esse trabalho em todos os.Você deve chamada MessageQueue.EndReceive() no evento.Só que o método pode lançar a exceção.Rever o código de exemplo do MSDN para o ReceiveCompleted evento.E não pegar de Exceção, que só faz com que undiagnosable falha.Pegar a exceção específica que você começa quando você eliminar a fila, 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();
        }

. . .

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top