views:

691

answers:

3

I send a message using the following code:

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

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

m_oMessageQueue.Send( message , myTransaction );

transaction.Commit( );

And receive it using a BeginRecieve and a ReceiveCompleted event handler.

If my event handler fails before calling EndRecieve, should the message remain on the queue and be available to a subsequent calls to receive? The behavior I am seeing is that the message is gone forever. (Or maybe there is a timeout after which point it will become available again?)

Update The code receiving the message looks like this.

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

For test purposes I throw an exception in the messageQueue_ReceiveCompleted_ThrowException event handler.

I then repeat the above code with a working event handler but i doesn't get called.

+2  A: 

Easiest resolution might be to use BeginPeek or Peek to read the contents of the message without removing it from the queue and once the message is processed, then take the message off the queue.

abit
+6  A: 

It looks like the problem is that you're using BeginReceive with a transactional queue. From MSDN:

Note Do not use the asynchronous call BeginReceive with transactions. If you want to perform a transactional asynchronous operation, call BeginPeek, and put the transaction and the (synchronous) Receive method within the event handler you create for the peek operation. Your event handler might contain functionality as shown in the following C# code.

For failures like this, I believe messages typically go into a dead letter queue or produce a negative acknowledgement, depending on how you configure the MessageQueue (which would explain why you aren't seeing them). You can read more about those options here.

Jeff Sternal
Thanks that should help me. Another related question, if I'm using Peek is there a possibility that the message would be picked up by multiple consumers?
tpower
Multiple consumers could `Peek` at the message, but only one would be able to actually `Receive` a particular message. This will probably require a little extra care since two consumers may be in there at the same time - you'll have to decide whether they're looking for that specific message (that `Peek` found), or any old message, and probably be sure to add a timeout to the `Receive` call so the loser doesn't block forever.
Jeff Sternal
+1  A: 

If the queue is transactional but remote, then you can only receive messages within a transaction with MSMQ 4.0.

How do I get transactional remote receives with MSMQ?

Cheers John Breakwell (MSFT)

John Breakwell