Domanda

Non capisco dove sta andando male. Fondamentalmente, ho un programma che riceve da una coda di messaggi e elabora i messaggi. Il programma può essere fermato in qualsiasi momento, nel qual caso il messaggio del messaggio ha finito ciò che sta facendo prima che il programma si chiuda. Sto cercando di realizzare questo con il seguente codice:

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

Come si spera evidente, il metodo di arresto dispone della coda dei messaggi, quindi attende che venga impostato il manubrio di attesa inattivo (che dovrebbe verificarsi come evento reciprometrato sarà chiamato quando è disposto, ma la proprietà E.Message dovrebbe tranne ).

Tuttavia, il ciclo del messaggio continua solo! Ho disposto la coda dei messaggi, ma riesce ancora a leggere da esso e il gestore di eccezione non è invocato, il che significa che la linea Idle.Wait attende per sempre.

La mia comprensione è che la disposizione di una coda di messaggi dovrebbe terminare qualsiasi in sospeso riceve e richiamare l'evento, ma l'E.Message (o Q.EndReceay) dovrebbe dare un'eccezione. Non è il caso? In caso contrario, in che altro modo posso uscire in sicurezza il mio messaggio loop?

Grazie

Aggiornamento:

Ecco un esempio completo (presuppone che la coda esiste)

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

È stato utile?

Soluzione 2

L'unico modo in cui potevo ottenere questo lavoro era con una coda transazionale.Qualsiasi coda non transazionale sembra essere vulnerabile a questo.Non una risposta, ma il miglior consiglio che posso dare a chiunque trovarlo.

Altri suggerimenti

Non è sicuro di come hai fatto questo lavoro. DEVE Chiama Messagequeue.EndReceive () nell'evento.Solo quel metodo può lanciare l'eccezione.Rivedere il codice di esempio MSDN per l'evento di credito.E non prendere eccezione, che causa solo un fallimento non diagnosble.Cattura l'eccezione specifica che ottieni quando dissipi la coda, ObjectDisosteconception.

    private static volatile bool _shouldStop = false;
.

...

            _shouldStop = true;
            mq.Close();
.

...

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

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

            mq.BeginReceive();
        }
.

...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top