Transactional Remote Receives in Message Queuing does not work as expected
One of my customers was trying to read a queue item within a DTC transactional context from a remote queue. He then aborted the transaction and expected to see the message back in the queue. However, that did not happen. He was trying to read from a Windows 7 machine. MSMQ was installed on a Windows Server 2008 R2 virtual machine. Both the machines were in the same domain.
He was using the code mentioned below :
using (var tran1 = new TransactionScope(TransactionScopeOption.Required))
{
using (var q1 = new MessageQueue(@"FormatName:Direct=OS:MachineName\private$\QueueName",true))
{
q1.Formatter = new BinaryMessageFormatter();
var newmsg1 = new MqProcessData(q1.Receive(MessageQueueTransactionType.Single).Body as string);
Assert.AreEqual(mqdata.EntityID, newmsg1.EntityID);
// Transaction.Current.Rollback();
q1.Close();
}
}
Using MessageQueueTransactionType.Single immediately commits after doing a remote read. So messages will not show up in the remote queue even if you try to abort the transaction.
So, here’s what I did.
I created test queue on a machine and posted 3 messages to that queue. From another machine, I ran the code mentioned below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Messaging;
using System.Transactions;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
using (var scope = new TransactionScope())
using (var queue = new MessageQueue("formatname:Direct=OS:MachineName\\private$\\QueueName", true))
{
// timeout should be higher for remote queues
// transaction type should be None for non-transactional queues
var message = queue.Receive(TimeSpan.FromMilliseconds(0), MessageQueueTransactionType.Automatic);
// ...normal processing...
scope.Complete();
}
}
}
}
At the mentioned below line of the code, I placed a breakpoint and started executing the code.
var message = queue.Receive(TimeSpan.FromMilliseconds(0), MessageQueueTransactionType.Automatic);
When I reached the above line, the message was read from the queue.
I did not allow scope.Complete(); to be executed. I then stopped debugging (as good as aborting the transaction) and I could see message back in the remote queue.
Note: MSMQ 4.0 introduced transactional remote receive as a native feature. An application that wants to perform a transactional remote receive can simply perform the remote receive in the context of a local Distributed Transaction Coordinator (MS DTC) transaction.
Written by
Kshitij Dattani
Reviewed by
Jainath Ramanathan
Microsoft India GTSC
Comments
- Anonymous
November 01, 2013
What about the performance? I dont get more than 15 trans / sec on a remote client :-(