7

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?

John Simons
  • 4,288
  • 23
  • 41
  • If the consumer instance has been created from a session, the session may have been created so that there is an ambient transaction around (Transaction.Current) during the delegate run. – Simon Mourier Apr 11 '13 at 10:26

2 Answers2

1

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();
}
Community
  • 1
  • 1
Paul Zahra
  • 9,522
  • 8
  • 54
  • 76
  • I need the actual dequeue of the messages to be enlisted in the `TransactionScope`, I don't see how this would solve anything! – John Simons Apr 12 '13 at 05:37
  • Why then aren't you using MessageQueueTransaction ? http://msdn.microsoft.com/en-us/library/system.messaging.messagequeuetransaction(v=vs.71).aspx – Paul Zahra Apr 12 '13 at 07:54
  • `MessageQueueTransaction` is used with `MessageQueue`, MSMQ. I am not using MSMQ, I am using WebSphereMQ – John Simons Apr 13 '13 at 07:19
  • Ah my bad... have you looked at http://stackoverflow.com/questions/3084849/how-to-do-a-transactional-get-from-websphere-mq-in-dotnet – Paul Zahra Apr 15 '13 at 08:10
1

A message listener a.k.a Asynchronous Consumer can't be used in a TransactionScopeas 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."

Shashi
  • 14,980
  • 2
  • 33
  • 52
  • Thanks! It would be really nice if the next version would support XA transactions with asynchronous consumers ;-) Does IBM has some kind of uservoice ? – John Simons Apr 16 '13 at 04:55
  • Yes. You can submit an RFE at: https://www.ibm.com/developerworks/rfe/?BRAND_ID=181. Once on this page click on the "submit RFE" link. – Shashi Apr 16 '13 at 05:12
  • Cool, I've submitted it (http://www.ibm.com/developerworks/rfe/execute?use_case=viewRfe&CR_ID=33621), please vote it up :) – John Simons Apr 16 '13 at 06:14