2009-01-26 6 views
4

Strange one. Nous avons une application multi-thread qui extrait les messages d'une file d'attente MSMQ et effectue ensuite des actions basées sur les messages. Tout cela est fait en utilisant DTC.MessageReadPropertyFilter réinitialisé lors de l'utilisation de MSMQ

Parfois, pour une raison que je ne peux pas décrire, nous obtenons des erreurs de lecture des messages lorsque nous retirons les messages de la file d'attente.

Le code qui est utilisé dans l'application:

Message[] allMessagesOnQueue = this.messageQueue.GetAllMessages(); 

foreach (Message currentMessage in allMessagesOnQueue) 
{ 
    if ((currentMessage.Body is IAMessageIDealWith)) 
    { 
       // do something;  
    } 
} 

Lorsque le currentMessage.Body est accessible, parfois il jette une exception:

System.InvalidOperationException: n'a pas été récupéré du corps lorsque la propriété recevoir le message. Assurez-vous que PropertyFilter est correctement défini. Maintenant, cela ne se produit que de temps en temps - et il semble que la valeur de la propriété Body soit False dans MessageReadPropertyFilter de la file d'attente.

Quant à savoir comment cela se passe, c'est un peu un mystère. La propriété Body est l'une des valeurs par défaut et nous ne la définissons jamais explicitement à false.

Est-ce que quelqu'un d'autre a vu ce genre de comportement ou a une idée de la raison pour laquelle cette valeur est définie comme étant fausse?

Répondre

3

Je l'ai vu aussi, et j'ai essayé de l'initialiser avec les propriétés auxquelles j'accède explicitement, et de ne les définir nulle part ailleurs. J'obtiens périodiquement la même erreur que vous obtenez, mon application est multi-threadée, ce que j'ai fini par faire est de piéger cette erreur et de me reconnecter à MSMQ quand je l'obtiens.

6

Comme mentionné plus haut, vous pouvez définir explicitement les valeurs booléennes sur l'objet System.Messaging.MessagePropertyFilter qui est accessible sur votre objet messageQueue via la propriété MessageReadPropertyFilter.

Si vous voulez toutes les données à extraire d'un message lors de la réception ou atteint un sommet, utilisez:

this.messageQueue.MessageReadPropertyFilter.SetAll(); // add this line 
Message[] allMessagesOnQueue = this.messageQueue.GetAllMessages(); 
// ... 

Cela peut nuire à la performance de lire de nombreux messages, donc si vous voulez seulement quelques propriétés supplémentaires, créer un nouveau MessagePropertyFilter avec des drapeaux personnalisés:

// Specify to retrieve selected properties. 
MessagePropertyFilter filter= new MessagePropertyFilter(); 
filter.ClearAll(); 
filter.Body = true; 
filter.Priority = true; 
this.messageQueue.MessageReadPropertyFilter = filter; 
Message[] allMessagesOnQueue = this.messageQueue.GetAllMessages(); 
// ... 

Vous pouvez également définir sur le défaut en utilisant:

this.messageQueue.MessageReadPropertyFilter.SetDefaults(); 

Plus d'infos ici: http://msdn.microsoft.com/en-us/library/system.messaging.messagequeue.messagereadpropertyfilter.aspx

1

Parfois, pour une raison quelconque, je ne peux pas décrire, nous obtenons un message lu des erreurs lors du retrait des messages de la file d'attente.

Êtes-vous en utilisant le même MessageQueue exemple de plus d'un fil, sans verrouillage? Dans ce cas, vous rencontrerez des changements parasites dans MessageReadPropertyFilter - au moins je l'ai fait, quand j'ai essayé.

Pourquoi?Because

Seule la méthode GetAllMessages est thread-safe.

Que pouvez-vous faire? Soit

  • Enroulez une serrure (_messageQueue) autour de tout accès à votre MessageQueue OU
  • créer plusieurs instances MessageQueue, un par fil
+0

Ce fut la réponse pour moi. +1 – SimonGoldstone