2011-11-15 23 views
9

"MessageQueueReceive"というクラスにこれを格納しています。トランザクションでMSMQ受信 - ロールバックでメッセージを再利用できない

public MessageQueueTransaction BlockingReceive(out Message message) 
{ 
    MessageQueueTransaction tran = null; 
    message = null; 

    tran = new MessageQueueTransaction(); 

    tran.Begin(); 
    try 
    { 
     message = Queue.Receive(new TimeSpan(0, 0, 5), tran); 
    } 
    catch (MessageQueueException ex) 
    { 
     // If the exception was a timeout, then just continue 
     // otherwise re-raise it. 
     if (ex.MessageQueueErrorCode != MessageQueueErrorCode.IOTimeout) 
      throw ex; 
    } 

    return tran; 

} 

その後、私の処理ループが、このあります: -

while (!Abort) 
{ 
    try 
    { 
     tran = this.Queue.BlockingReceive(out msg); 

     if (msg != null) 
     { 
      // Process message here 

      if (tran != null) 
       tran.Commit(); 
     } 
    } 
    catch (Exception ex) 
    { 
     if (tran != null) 
      tran.Abort(); 

    } 
} 

コントロールパネルツールは、私が使用しているメッセージキューがトランザクションであることを示しています。ジャーナルキューが有効になっていません。

このコードでは、キューを作成します - これが呼ばれたとき

private static MessageQueue CreateMessageQueue(string queueName, bool transactional = false) 
{ 
    MessageQueue messageQueue = MessageQueue.Create(queueName, transactional); 
    messageQueue.SetPermissions("Administrators", MessageQueueAccessRights.FullControl, 
      AccessControlEntryType.Allow); 
    return messageQueue; 
} 

トランザクションのパラメータが「真」に設定されています。私が見つける何

は、例外は、メッセージの処理中に発生した場合に、tran.Abortが呼び出されるということですが、その時点で私は、メッセージがキューに戻されることを期待したいです。しかし、これは起こっておらず、メッセージは失われています。

明らかなものがありませんか?誰かが私が間違っているのを見ることができますか?

+0

受信しているキューはリスナーサービスのローカルにありますか? –

+0

はい、送受信プロセスとキューはすべて同じボックスにあります。それらはプライベートキューです。また、同じコードをいくつかの異なるボックスで実行し、すべて同じ問題を参照してください。これは、マシンに関する奇妙なものではなく、このコードに関連していることを示唆しています。 – JohnCC

+0

明白な質問でしょう。中断して例外を叩いていると確信していますか?捕捉された後で投げ捨てられるメッセージ処理コードに例外がスローされた可能性はありますか? –

答えて

5

すべてのコメントありがとうございます。私はRussell McClureが提案したコードを再構成しました。単純なテストケースを作成しようとしましたが、問題を再現できませんでした。最後に

私は(どのくらいの頻度ことが起こるのでしょうか?)探していたところ、問題は全くありませんでした。私のパイプラインで

は、私は、重複メッセージチェッカーを持っていました。私のシステムが扱う「メッセージ」は、WAN上のリモートデバイスからのものであり、時折、ワイヤ上のメッセージが複製されます。メッセージがMSMQから引き出されたとき

は、データベースライタチェッカー重複を介して通過します。データベースライターに障害が発生した場合、重複チェックではそのテーブルからハッシュが削除されませんでした。プロセスがループを再試行しようとすると、MSMQトランザクションがデータベース作成者が失敗したときにロールバックされたため、キューのaganから同じメッセージが取得されます。しかし、2回目の試みでは、重複したチェッカーは以前にそのメッセージを見たことがあり、それを静かに飲み込んでしまうでしょう。

修正は、例外がチェーン内の次のリンクから重複チェッカースポットを行い、ロールバック、それはあまりにも行っていた何かをすることでした。

1

必要なものを得るために、キューをトランザクションキューとして作成する必要があります。

enter image description here

EDIT:

さて、あなたのキューは、私はそれが起こっている、具体的方法を確認することはできませんが、あなたは、あなたの取引を誤操作しているという事実を指すこと、その後のトランザクションである場合。 BlockingReceiveメソッドを変更してメッセージを返します。 MessageQueueTransactionの作成を外側のメソッドに移動します。同じメソッドでBegin、Commit、Abortメソッドの呼び出しを行うと、コードの保守性が大幅に向上します。

+0

こんにちは!キューは、確実にトランザクションキューとして作成されます。コンピュータの管理 - >サービスとアプリケーション - >メッセージキューでキューのプロパティを見ると、トランザクションとして表示されます。 – JohnCC

関連する問題