1

例外的ではない条件に例外を使用するべきではないことはわかっていますが、これを実行して、自分がやりたいことが本当に悪いかどうかを確認したかったのです。

MSMQ メッセージ キューからメッセージを取得しようとするルーチンがあります。キューに利用可能なメッセージがない場合は、セカンダリ ソースをチェックして、そこで利用可能なメッセージがあるかどうかを確認します。ルーチンの例は次のとおりです。

void CheckForMessages(out Message msg, TimeSpan timeout)
{
   try
   {
      queue.Peek(timeout);
   }
   catch(MessageQueueException ex)
   {
      if (e.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout)
      {
         if (messageAvailable)
         {
            msg = SecondaryMessageSource();
         }

      }

      throw;
   }

   msg = queue.Receive();
}

MSMQ には、キュー上のメッセージ数をチェックするメカニズムはありません。メッセージが利用可能かどうかを判断する唯一の方法は、Peek を使用することです。エラーが IOTimeout に設定された状態で MessageQueueException が発生した場合は、Peek がタイムアウトになり、キューにメッセージがありません。

このルーチンは、メッセージの取得のみを目的とするスレッドのループ内で呼び出されます。タイムアウトはミリ秒の範囲になります。コール スタックは 1 つのメソッドで構成され、スレッドはそれ以外の処理を担当しません。メソッドが常に例外をスローすることはわかっていますが、これは悪い習慣と見なされていますが、この場合、本当に悪いことなのでしょうか? もしそうなら、コードが完全に複雑になることなくこのタスクを達成する方法について誰か提案がありますか?

4

3 に答える 3

2

プログラム ロジック (一方のキューを確認し、メッセージがない場合はもう一方を確認する) と、MSMQ の動作方法のために、例外に対処する必要があります。ただし、そのコードを catch 句に含めるよりも、おそらくよりエレガントな方法があると思います。

これが私がすることです:

private const int ReceiveTimeout = xxxx;

private bool TryReceiveMessage(MessageQueue queue, out Message message)
{   
    try
    {
        message = queue.Receive(ReceiveTimeout);

        // if we made it here, we are good and have a message
        return true;
    }
    catch(MessageQueueException ex)
    {
        if (MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout)
        {
             // this is not exceptional to us, so just return false
             return false;
        }

        // Throw anything else as it is unexpected
        throw;
    }    
}

次に、呼び出しメソッドを次のようにコーディングします。

private Message MyMethodThatIsCalledInALoop()
{
   // These could also be params, etc.
   MessageQueue primary = // whatever code to get a reference to your primary queue
   MessageQueue secondary = // whatever code to get a reference to your secondary queue

   Message message = null;

   if (TryReceiveMessage(primary, out message))
   {
       return message;
   }

   if (TryReceiveMessage(secondary, out message))
   {
       return message;
   }

   // this would still be null
   return message;
}
于 2013-05-13T12:11:18.313 に答える
0

MSMQ には、キュー上のメッセージ数をチェックするメカニズムはありません。メッセージが利用可能かどうかを判断する唯一の方法は、Peek を使用することです。エラーが IOTimeout に設定された状態で MessageQueueException が発生した場合は、Peek がタイムアウトになり、キューにメッセージがありません。

あなたは自分で答えました。他に方法がないので、どのような選択肢がありますか?

于 2013-05-13T11:27:22.710 に答える
0

ポーリング ジョブごとに 2 つの個別のスレッドを作成し、それらのメッセージを同期キューに格納して、マスター スレッドがそれらを並べ替えてそこから適切なメッセージを取得できるようにする必要があります。このようにして、呼び出しに「無限」のタイムアウトを設定できPeekます。

于 2013-05-13T11:28:17.027 に答える