Attualmente sto avendo un problema di perdere un messaggio. Questo errore si verifica raramente, ma accade abbastanza spesso da risultare fastidioso. Ecco il contesto del problema:È possibile perdere i messaggi utilizzando MSMQ MessageQueue.Peek con un timeout?
- Ho attivato il giornale dei messaggi su goldmine_service_queue, un MSMQ su un server Windows 2003.
- Posso provare che il messaggio viene inserito in goldmine_service_queue poiché il messaggio viene visualizzato nel giornale dei messaggi. Queste informazioni forniscono informazioni sul momento in cui il messaggio è scomparso.
- Le funzioni di registrazione utilizzano http://logging.apache.org/log4net/index.html
- I registri non mostrano errori.
- La funzione di lavoro (illustrata di seguito) viene eseguita all'interno di un thread di un servizio di Windows. È responsabile di dare una occhiata ai messaggi (oggetti di lavoro) dalla coda ed elaborarli.
- Dai registri, ho il forte sospetto che il mio problema potrebbe riguardare MessageQueue.Peek e il comportamento scaduto.
È possibile che il timeout e la ricezione del messaggio si verifichino contemporaneamente? C'è un modo migliore per me di gestire il controllo degli arresti del servizio per evitare questo errore?
private void workerFunction()
{
logger.Info("Connecting to queue: " + Settings.Default.goldmine_service_queue);
MessageQueue q = new MessageQueue(Settings.Default.goldmine_service_queue);
q.Formatter = new ActiveXMessageFormatter();
while (serviceStarted)
{
Message currentMessage = null;
try
{
currentMessage = q.Peek(new TimeSpan(0,0,30));
}
catch (System.Messaging.MessageQueueException mqEx)
{
if (mqEx.ToString().Contains("Timeout for the requested operation has expired"))
{
logger.Info("Check for service stop request");
}
else
{
logger.Error("Exception while peeking into MSMQ: " + mqEx.ToString());
}
}
catch (Exception e)
{
logger.Error("Exception while peeking into MSMQ: " + e.ToString());
}
if (currentMessage != null)
{
logger.Info(currentMessage.Body.ToString());
try
{
ProcessMessage(currentMessage);
}
catch (Exception processMessageException)
{
logger.Error("Error in process message: " + processMessageException.ToString());
}
//Remove message from queue.
logger.Info("Message removed from queue.");
q.Receive();
//logPerformance(ref transCount, ref startTime);
}
}//end while
Thread.CurrentThread.Abort();
}
Grazie per la risposta: - per quanto riguarda le condizioni di gara: non sono sicuro di vedere le condizioni di gara che menzionate. Secondo http://msdn.microsoft.com/en-us/library/t5te2tk0.aspx, MessageQueue.Peek (Timeout) è una chiamata bloccante. - Sono preoccupato per l'utilizzo di un modello asincrono poiché ProcessMessage esegue alcune operazioni COM. Non so se queste operazioni sono thread-safe. io sono ok con il tentativo di utilizzare ricezione() al posto del picco solo che non so come creare la possibilità di fermare il ciclo while a causa di un arresto di servizio. –
Re: COM in 'ProcessMessage': non dovrebbe essere un problema se solo un thread sta eseguendo' ProcessMessage' (che può essere ottenuto nel caso async solo avviando una nuova ricezione asincrona dopo il completamento di 'ProcessMessage'. In async caso si chiude la coda (e si svuota la cache --- in base ad alcune ricerche questo sembra essere necessario per chiudere realmente la connessione) e qualsiasi ricezione in attesa verrà annullata .Non c'è loop da cancellare. – Richard