2009-09-10 5 views
3

J'envoie un message en utilisant le code suivant:Un message System.MessageQueue (MSMQ) est-il perdu si ma fonction échoue lors du traitement?

var transaction = new MessageQueueTransaction()) 
transaction.Begin(); 

var message = new Message 
{ 
    Body = myContent, 
    Recoverable = true 
}; 

m_oMessageQueue.Send(message , myTransaction); 

transaction.Commit(); 

Et reçois l'aide d'un BeginRecieve et un gestionnaire d'événements ReceiveCompleted.

Si mon gestionnaire d'événements échoue avant d'appeler EndRecieve, le message doit-il rester dans la file d'attente et être disponible pour les appels suivants à recevoir? Le comportement que je vois est que le message est parti pour toujours. (Ou peut-être y at-il un délai après lequel il redeviendra disponible?)

Mise à jour Le code qui reçoit le message ressemble à ceci.

var messageQueue = new MessageQueue(myPath); 
messageQueue.ReceiveCompleted += messageQueue_ReceiveCompleted_ThrowException; 
messageQueue.BeginReceive(); 

Pour des fins de test j'fous une exception dans le gestionnaire d'événements messageQueue_ReceiveCompleted_ThrowException. Je répète ensuite le code ci-dessus avec un gestionnaire d'événements de travail mais je ne suis pas appelé.

+0

quel est votre file d'attente de EnableConnectionCache reçoivent la valeur? –

+0

Je ne l'ai pas mis à quoi que ce soit, à quoi sert-il? – tpower

Répondre

9

Il semble que le problème est que vous utilisez BeginReceive avec une file d'attente transactionnelle. From MSDN:

Remarque Ne pas utiliser l'appel asynchrone BeginReceive avec des transactions. Si vous souhaitez effectuer une opération asynchrone transactionnelle, appelez BeginPeek, et de mettre la transaction et la (synchrone) méthode receive dans le gestionnaire d'événements vous créez pour l'opération de coup d'oeil. Votre gestionnaire d'événement peut contenir la fonctionnalité indiquée dans le code C# suivant.

Pour les échecs comme celui-ci, je crois que les messages vont généralement dans une file d'attente de lettre morte ou produire un accusé de réception négatif, selon la façon dont vous configurez le MessageQueue (ce qui expliquerait pourquoi vous ne les voyez). Vous pouvez read more about those options here.

+0

Merci cela devrait m'aider. Une autre question connexe, si j'utilise Peek est-il une possibilité que le message serait repris par plusieurs consommateurs? – tpower

+1

Plusieurs consommateurs pourraient jeter un coup d'œil au message, mais un seul serait en mesure de recevoir un message particulier. Cela nécessitera probablement un peu plus de soin puisque deux consommateurs peuvent être présents en même temps - vous devrez décider s'ils sont à la recherche de ce message spécifique (que 'Peek' trouvé), ou tout autre message, et probablement assurez-vous d'ajouter un délai à l'appel 'Receive' afin que le perdant ne bloque pas pour toujours. –

+0

BeginPeek, puis plus tard ReceiveById en utilisant l'Id passé dans le PeekCompleted, être une meilleure approche? –

2

La résolution la plus facile pourrait être d'utiliser BeginPeek ou Peek pour lire le contenu du message sans le retirer de la file d'attente et une fois le message traité, puis retirer le message de la file d'attente.

Questions connexes