J'ai actuellement un problème de perte de message. Cette erreur se produit rarement, mais arrive assez souvent pour être ennuyante. Voici le contexte du problème:Est-il possible de perdre des messages en utilisant MSMQ MessageQueue.Peek avec un délai d'expiration?
- J'ai activé le journal des messages sur goldmine_service_queue, un MSMQ sur le serveur Windows 2003.
- Je peux prouver que le message est en train d'être inséré dans goldmine_service_queue puisque le message apparaît dans le journal des messages. Cette information donne des informations sur le moment où le message a disparu.
- Les fonctions de journalisation utilisent http://logging.apache.org/log4net/index.html
- Les journaux ne présentent pas d'erreurs.
- La fonction worker (illustrée ci-dessous) s'exécute dans un thread d'un service Windows. Il est responsable de jeter un coup d'œil aux messages (éléments de travail) de la file d'attente et de les traiter. À partir des journaux, je soupçonne fortement que mon problème peut être lié au comportement MessageQueue.Peek et au délai d'expiration.
Est-il possible que le timeout et la réception de message se produisent en même temps? Y a-t-il une meilleure façon pour moi de gérer les arrêts de service pour éviter cette erreur?
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();
}
Merci pour la réponse: - en ce qui concerne les conditions de course: Je ne suis pas sûr de voir les conditions de course que vous mentionnez. Selon http://msdn.microsoft.com/en-us/library/t5te2tk0.aspx, MessageQueue.Peek (Timeout) est un appel bloquant. - Je suis préoccupé par l'utilisation d'un modèle asynchrone car ProcessMessage effectue certaines opérations COM. Je ne sais pas si ces opérations sont thread safe. Je suis d'accord pour essayer d'utiliser Receive() au lieu de peak, sauf que je ne sais pas comment créer l'opportunité d'arrêter la boucle while en raison d'un arrêt de service. –
Re: COM dans 'ProcessMessage': ne devrait pas poser de problème si un seul thread exécute' ProcessMessage' (ce qui peut être réalisé dans le cas asynchrone en démarrant seulement une nouvelle réception asynchrone après la fin de 'ProcessMessage'.) En async Si vous fermez la file d'attente (et vider le cache --- en fonction d'une recherche, cela semble être nécessaire pour vraiment fermer la connexion) et toute réception en attente sera annulée Il n'y a pas de boucle à annuler – Richard