Message Queue and Distributed transactions

G

Guest

Hi.

The problem is a bit hard to explain.
I have a ServicedComponent method which runs a distributed transaction
consisting on a a MessageQueue reception and several database operations.
That ServicedComponent method is called from a pool of threads which get
blocked in the Receive method of the queue. At that moment there are as many
open transactions in the DTC as the number of threads in the pool. After 60
seconds of inactivity the transactions get cancelled by the DTC and the
threads get unblocked and everything starts again. My question is, how can I
achieve that a thread calls the ServicedComponent method (and thus starts a
new transaction) only when there is a message on the queue to be received?.

The problem is I get a lot of cancelled transactions because of timeouts of
the DTC, as I need a distributed transaction i cannot use the BeginReceive
method. If I use the BeginPeek method and instance the ServicedComponent on
the PeekCompleted, all the threads get unblocked and the same problem arises
again. Can anybody help me?

this is my code:

class Worker {
private int threadId;

public Worker (int threadId) {
this.threadId=threadId;
}

//doWork is the ThreadStart method
public void doWork() {
//ShippingProcess.endShippingProcess is a static bool field
while (!ShippingProcess.endShippingProcess) {
try {
using (MessageHandler mh = new MessageHandler()) {
mh.handleMessage();
}
}
catch (Exception e) {
//Write EventLogEntry
}
}
}
}

[Transaction(TransactionOption.Required)]
public class MessageHandler : ServicedComponent {
public MessageHandler() {
}

[AutoComplete()]
public void handleMessage() {
SHQM shippingMessage;
STQM stockMessage;

using (MessageQueue queue = new MessageQueue(SHIPPING_QUEUE_STRING)) {
try {
Type[] shipMessageType = {typeof(SHQM)};
queue.Formatter = new XmlMessageFormatter(shipMessageType);
//ALL THE THREADS GET BLOCKED HERE
shippingMessage =
(SHQM)queue.Receive(MessageQueueTransactionType.Automatic).Body;
}
catch (MessageQueueException e) {
//Write EventLog
throw;
}
catch (Exception e) {
//Write EventLog
throw;
}
}
//DB operatios go here
}
}
}


Regards, Rodrigo.
 
G

Guest

Hi Rodrigo,

You can use:

try
{
queue.Receive(TimeSpan.Zero, MessageQueueTransactionType.Automatic);
}
catch(MessageQueueException e)
{
if( e.MessageQueueErrorCode.IOTimeout )
{
//Do what ever you want when there is no message in the queue.
}
}

Regards,

Dinh Duy Tran
[MCSD/CSDP]
 
G

Guest

Thanks for your advice.

If I do what you say, there will be more cancelled transactions.
The threads shouldn't create an instance of 'Distributed' if there aren't
messages on the queue. If you put a timeout of zero seconds, the threads will
be creating and destroying transactions if there aren't messages on the queue.

I tried with a BeginPeek call on the threads, but it didn't work as expected.

The goal is to get the threads blocked until there is a message but without
calling Receive or BeginReceive

Any more ideas would be helpful.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top