MessageQueue.Send occasionally fails with InvalidOperationException, BadEnumerator
I have a non-tx queue with a receiver in one process and a PowerShell script which uses the MessageQueue.Send( object, label ) method to enqueue messages. Occasionally I get this weird error in the PowerShell script (the sender):
An error occurred while enumerating through a collection: Message that the cursor is currently pointing to has been removed from the queue by another process or by another call to Receive without the use of this cursor..
+ CategoryInfo : InvalidOperation: (System.Messaging.MessageEnumerator:MessageEnumerator) [], RuntimeException
+ FullyQualifiedErrorId : BadEnumeration
I can't understand how the MessageEnumerator gets involved in the sending part? Any clues?
The receiving part (service written in .net also using System.Messaging to interact with MSMQ) is doing its work in a while loop in which it does a queue.Peek( 1s timeout ) and then a call to queue.Receive(). All MSMQ exceptions are logged by the receiver, but the log is empty. All errors oc开发者_如何学JAVAcurs in the sending PowerShell script.
The receiver is old known-to-be-working code but the script is new and untested. During my tests I got no errors on the test machine, where no receiver was hooked up.
First shot with the receiver hooked up, some of the calls to MessageQueue.Send() resulted in an error.
That script looked like this:
begin {
$q = Create-QueueInstance
}
process {
$messagesToSend | %{
Send-Message $q $_
}
}
end {
$q.Dispose()
}
Second shot I tried to dispose the queue instance in each iteration, if the issue was related to shared resources not being freed up, etc:
That script looked like this:
process {
$messagesToSend | %{
$q = Create-QueueInstance
Send-Message $q $_
$q.Dispose()
}
}
The error still occurs, but I believe it occurs less frequent.
I use the default constructor to create the queue intance, no customization of DefaultPropertiesToSend or anything. The messages are XML serializable objects, producing about a message body of 300 bytes. The queue, sender and receiver are located on the same machine.
Why does the service do a Peek-then-Receive?
Is it checking that the message is the one it wanted or not?
If so, do you use PeekNext to move down the queue?
Is the receiver service multi-threaded?
Just trying to work out where cursors comes into it.
Pretty weird problem.
Cheers John Breakwell
精彩评论