简体   繁体   English

Windows非WCF服务将事务处理的MSMQ消息移到失败的队列

[英]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. 我有一个在Server 2008上运行的旧版Windows服务,该服务从事务MSMQ队列读取消息。 This is not configured as a WCF service. 配置为WCF服务。

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. 我们希望通过捕获自定义异常并将相关消息发送到单独的“失败”或“毒药”队列中,具体取决于抛出的异常类型,从而改进代码(C#4.0)中失败和有毒消息​​的处理。

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. 我无法获取Catch代码以将消息发送到单独的队列-它从原始队列中消失(根据需要!),但未显示在“失败”队列中。

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: 我们简化的PeekCompleted事件代码:

 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 编辑:2013年10月8日

Hugh's answer below got us on the right track. 休的以下回答使我们走上了正确的道路。 Inside the Catch block the Failed Queue was already created as transactional 在Catch块内,失败队列已创建为事务性队列

MessageQueue.Create(qname , true);

but the Send needed a TransactionType parameter 但是发送需要一个TransactionType参数

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). 如果消息从您的原始队列中消失,则意味着您的代码已到达第二个作用域。Complete()(在catch块中)。

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. 看看是否可行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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