I'm using the IBM.XMS lib to talk to WebSphereMQ.
When receiving messages using the synchronous method, eg:
using (var scope = new TransactionScope(TransactionScopeOption.Required, transactionOptions))
{
message = consumer.Receive(1000);
if (message != null)
{
//Do work here
scope.Complete();
}
}
But if I want to use the asynchronous method:
consumer.MessageListener = delegate(IMessage msg)
{
//Do work here
//But where do I put TransactionScope?
};
I can't work out how to wrap the MessageListener
callback within a TransactionScope
.
Does anyone know how to do this?
A message listener a.k.a Asynchronous Consumer can't be used in a TransactionScope
as the message listener runs on a different thread than the thread that created the TransactionScope
. You can only use the synchronous Receive/Send inside a TransactionScope
.
This link says "The XA transactions are not supported in asynchronous consumers."
It may well be worth your while investigating using DependentClone to create a DependentTransaction.
"A dependent transaction is a transaction whose outcome depends on the outcome of the transaction from which it was cloned."
"The DependentTransaction is a clone of a Transaction object created using the DependentClone method. Its sole purpose is to allow the application to come to rest and guarantee that the transaction cannot commit while work is still being performed on the transaction (for example, on a worker thread)."
Edit: Just spotted this in the related SO questions list: related question and answer see the msdn link they supplied: well worth a read Managing Concurrency with DependentTransaction
Taken from the MSDN link above (for brevity):
public class WorkerThread
{
public void DoWork(DependentTransaction dependentTransaction)
{
Thread thread = new Thread(ThreadMethod);
thread.Start(dependentTransaction);
}
public void ThreadMethod(object transaction)
{
DependentTransaction dependentTransaction = transaction as DependentTransaction;
Debug.Assert(dependentTransaction != null);
try
{
using(TransactionScope ts = new TransactionScope(dependentTransaction))
{
/* Perform transactional work here */
ts.Complete();
}
}
finally
{
dependentTransaction.Complete();
dependentTransaction.Dispose();
}
}
//Client code
using(TransactionScope scope = new TransactionScope())
{
Transaction currentTransaction = Transaction.Current;
DependentTransaction dependentTransaction;
dependentTransaction = currentTransaction.DependentClone(DependentCloneOption.BlockCommitUntilComplete);
WorkerThread workerThread = new WorkerThread();
workerThread.DoWork(dependentTransaction);
/* Do some transactional work here, then: */
scope.Complete();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With