简体   繁体   中英

Windows Non-WCF Service Moving Transacted MSMQ Message to Failed Queue

I have a legacy Windows service running on Server 2008 that reads messages from a Transactional MSMQ Queue. This is not configured as a WCF service.

We are wanting to improve the handling of failed and poison messages in code (C# 4.0) by catching custom exceptions and sending the related message to a separate 'failed' or 'poison' queue depending upon the type of exception thrown.

I can't get the Catch code to send the message to the separate queue - it disappears from the original queue (as desired!) but doesn't show up in the 'failed' queue.

For testing all of the queues have no Authentication required and permissions are set to allow Everyone to do everything.

Clearly something is missing or wrong and I suspect it is transaction related, but I can't see it. Or perhaps this is not possible the way I am trying to do it ?

Any guidance / suggestions appreciated!

Our simplified PeekCompleted Event code:

 private void MessageReceived(object sender, PeekCompletedEventArgs e)
    {

        using (TransactionScope txnScope = new TransactionScope())
        {
            MyMessageType currentMessage = null;
            MessageQueue q = ((MessageQueue)sender);
            try
            {
                Message queueMessage = q.EndPeek(e.AsyncResult);
                currentMessage = (FormMessage)queueMessage.Body;
                Processor distributor = new Processor();

                Processor.Process(currentMessage); // this will throw if need be

                q.ReceiveById(e.Message.Id);
                txnScope.Complete();
                q.BeginPeek();
            }
            catch (MyCustomException ex)
            {
                string qname = ".\private$\failed";
                if (!MessageQueue.Exists(qname)){
                     MessageQueue.Create(qname , true);
                }
                MessageQueue fq = new MessageQueue(qname){
                    Formatter = new BinaryMessageFormatter()
                };
                System.Messaging.Message message2 = new System.Messaging.Message{
                    Formatter = new BinaryMessageFormatter(),
                    Body = currentMessage,
                    Label = "My Failed Message";
                };
                fq.Send(message2);           //send to failed queue
                q.ReceiveById(e.Message.Id); //off of original queue
                txnScope.Complete();         // complete the trx
                _queue.BeginPeek();          // next or wait
            }
            //other catches handle any cases where we want to tnxScope.Dispose()

EDIT : October 8, 2013

Hugh's answer below got us on the right track. Inside the Catch block the Failed Queue was already created as transactional

MessageQueue.Create(qname , true);

but the Send needed a TransactionType parameter

fq.Send(message2,MessageQueueTransactionType.Single);

That did the trick. Thanks Hugh!

If the message is disappearing from your original queue then that means your code is reaching the second scope.Complete() (in your catch block).

This means the problem has to do with your send to the error queue.

I would suggest that you need to create the queue as transactional because you are sending from within a scope.

MessageQueue fq = new MessageQueue(qname, true){
    Formatter = new BinaryMessageFormatter()
};

Then you need to do a transactional send:

fq.Send(message2, Transaction.Current);

See if this works.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM