Je suis actuellement en train de perdre un message. Cette erreur se produit rarement, mais se produit assez souvent pour être ennuyeux. Voici le contexte de la question:
est-il possible pour le délai d'attente et le message reçoive de se produire en même temps? Existe-t-il une meilleure façon pour moi de gérer le service Arrêter la vérification pour éviter cette erreur? P>
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(); }
3 Réponses :
Je ne pense pas que les messages soient manqués en fonction d'un examen rapide, mais vous travaillez de manière très étrange avec beaucoup de possibilités de conditions de course. P>
Pourquoi ne pas simplement recevoir le message et le transmettre à Aussi, plutôt que d'interroger la file d'attente, pourquoi ne pas recevoir une réception asynchrone et laisser le piscine de thread gérer l'achèvement (où vous devez appeler En outre, abandonner le thread est un moyen vraiment mauvais de sortir, il suffit de revenir de la fonction de démarrage du fil. P> ProcessMessage CODE> (si
ProcessMessage code> échoue, vous effectuez une lecture de toute façon). Si vous avez besoin de gérer plusieurs récepteurs, effectuez la réception dans une transaction MSMQ afin que le message soit indisponible par d'autres récepteurs, mais non retiré de la file d'attente jusqu'à ce que la transaction soit commise. P>
endreceive code>). Cela sauve attacher un fil, et vous n'avez pas besoin d'une fermeture d'un service de cas spécial (fermez la file d'attente de messagerie, puis appelle
message ceinture.clearconnectioncache (); p>). P>
Merci pour la réponse: - En ce qui concerne les conditions de course: Je ne sais pas si je vois les conditions de course que vous mentionnez. Selon msdn.microsoft.com/en-us/library/t5te2tk0.aspx < / a>, messagequeuse.peek (timeout) est un appel de blocage. - Je suis préoccupé par l'utilisation d'un modèle ASYNC car ProcessMessage effectue certaines opérations COM. Je ne sais pas si ces opérations sont en sécurité. J'essaye d'essayer d'utiliser Recevoir () au lieu d'un pic, sauf que je ne sais pas comment créer la possibilité d'arrêter la boucle de temps en raison d'un arrêt de service.
RE: COM dans ProcessMessage CODE>: ne doit pas être un problème si un seul thread est en cours d'exécution
ProcessMessage code> (qui peut être obtenu dans l'affaire ASYNC en démarrant uniquement une nouvelle ASYNC recevoir après < Code> ProcessMessage CODE> est terminé. Dans le cas ASYNC, vous fermez la file d'attente (et affleurez le cache - sur la base de certaines recherches, cela semble être nécessaire pour fermer la connexion) et tout reçu en attente sera annulé. Là n'est pas une boucle à annuler.
Je dois être ce changement Edit: aussi pour votre récaptation d'exception - Vous pouvez vérifier si votre exception est une exception temporelle en comparant le code d'erreur. P> < Pré> xxx pré> où MQE est votre exception de la file d'attente de message. Vous pouvez aimer cela mieux qu'une comparaison de chaîne. P> p> couranteMessage = q.eek (nouveau Timespan (0,0,30)); code> à
actuelMessage = q.receive (); code> va réparer votre problème. J'utilise MSMQ pour un message qui passe dans le même contexte, mais utilisez uniquement le coup d'œil (et attendre une exception de délai d'expiration) pour déterminer si la file d'attente est vide. L'appel à
recevoir code> bloque cependant alors planez-plan en conséquence.
J'utilise message rsp = colastatus.receivebycorrélationid (corrélationid, nouvelle trimestre (0, délai d'attente, 0)); code>. Je suis confus si 5 minutes est très élevée pour le délai d'attente. IMHO, je pense que mieux est inférieur à 1 minute.
Quelques commentaires pour clarifier comment MSMQ fonctionne ici. P>
"Je peux prouver que le message est inséré dans GoldMine_Service_Queue car le message apparaît dans le journal de messagerie. P>
Le message passe dans la file d'attente du journal lorsque le message d'origine est supprimé du GoldMine_Service_Queue. Vous pouvez donc dire que le message a été livré avec succès à la file d'attente et retiré avec succès de la file d'attente. P>
"Je soupçonne fortement que mon problème puisse se rapporter à la messagerie d'un message et du comportement Time Out." p>
Un coup d'oeil ne fait rien pour supprimer le message de la file d'attente. Seulement "Q.Receive ();" est-ce que. Dans votre code, il n'y a pas de connexion explicite entre le message qui a été découvert et celui reçu. "Q.Receive ();" Dit juste "recevoir un message de la file d'attente". Dans un environnement multi-threadé, vous pouvez vous attendre à avoir des messages de lecture de manière incohérente - certains pouvaient être découverts et traités plusieurs fois. Vous devriez obtenir l'identifiant du message d'un coup d'œil et utiliser RECEVÉBYID afin que vous ne puissiez recevoir que le message d'un coup d'œil. P>