【问题标题】:Windows Non-WCF Service Moving Transacted MSMQ Message to Failed QueueWindows 非 WCF 服务将 Transacted MSMQ 消息移动到失败队列
【发布时间】:2013-10-14 17:20:36
【问题描述】:

我有一个在 Server 2008 上运行的旧版 Windows 服务,它从事务性 MSMQ 队列中读取消息。这配置为 WCF 服务。

我们希望通过捕获自定义异常并将相关消息发送到单独的“失败”或“中毒”队列(取决于抛出的异常类型)来改进代码(C# 4.0)中失败和中毒消息的处理。

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

为了测试所有队列都不需要身份验证,并且权限设置为允许每个人做任何事情。

显然有些东西丢失或出错了,我怀疑它与交易有关,但我看不到它。或者也许这不可能像我试图做到的那样?

任何指导/建议表示赞赏!

我们简化的 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()

编辑:2013 年 10 月 8 日

Hugh 在下面的回答让我们走上了正轨。在 Catch 块中,Failed Queue 已经创建为事务性的

MessageQueue.Create(qname , true);

但是 Send 需要一个 TransactionType 参数

fq.Send(message2,MessageQueueTransactionType.Single);

成功了。谢谢休!

【问题讨论】:

    标签: c# transactions windows-services msmq


    【解决方案1】:

    如果消息从您的原始队列中消失,则意味着您的代码正在到达第二个 scope.Complete()(在您的 catch 块中)。

    这意味着问题与您发送到错误队列有关。

    我建议您需要将队列创建为事务性的,因为您是从范围内发送的。

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

    然后你需要做一个事务性发送:

    fq.Send(message2, Transaction.Current);
    

    看看这是否有效。

    【讨论】:

    • 嗨,休 - 再次感谢!这是事务发送 - 它需要第二个参数是事务类型 fq.Send(message2,MessageQueueTransactionType.Single);谢谢队长!
    猜你喜欢
    • 2014-07-20
    • 2011-07-31
    • 2011-06-02
    • 1970-01-01
    • 2013-12-31
    • 2012-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多