9

n個のメッセージキューからメッセージを受信するサービスがあります。ただし、メッセージキューサービスを再起動すると、メッセージキューサービスが正常に再起動した後でも、メッセージ取得サービスはメッセージの受信を停止します。

メッセージ取得サービスでスローされたMessageQueueExceptionを具体的にキャッチし、キューのBeginReceiveメソッドを再度呼び出しようとしました。ただし、メッセージキューサービスの再起動にかかる2秒ほどで、約1875の例外インスタンスが発生し、StartListeningメソッドで別のMessageQueueExceptionがスローされると、サービスが機能を停止します。

メッセージキューサービスの再起動から回復するためのエレガントな方法はありますか?

    private void OnReceiveCompleted(object sender, ReceiveCompletedEventArgs e)
    {
        MessageQueue queue = (MessageQueue)sender;

        try
        {
            Message message = queue.EndReceive(e.AsyncResult);

            this.StartListening(queue);

            if (this.MessageReceived != null)
                this.MessageReceived(this, new MessageReceivedEventArgs(message));
        }
        catch (MessageQueueException)
        {
            LogUtility.LogError(String.Format(CultureInfo.InvariantCulture, StringResource.LogMessage_QueueManager_MessageQueueException, queue.MachineName, queue.QueueName, queue.Path));
            this.StartListening(queue);
        }            
    }

    public void StartListening(MessageQueue queue)
    {
        queue.BeginReceive();
    }

これが引き起こす無限ループの問題に対処し、少しクリーンアップする必要がありますが、あなたはその考えを理解しています。

MessageQueueExceptionが発生したら、RecoverQueueメソッドを呼び出します。

    private void RecoverQueue(MessageQueue queue)
    {            
        string queuePath      = queue.Path;
        bool   queueRecovered = false;

        while (!queueRecovered)
        {
            try
            {
                this.StopListening(queue);
                queue.Close();
                queue.Dispose();

                Thread.Sleep(2000);

                MessageQueue newQueue = this.CreateQueue(queuePath);

                newQueue.ReceiveCompleted += new ReceiveCompletedEventHandler(this.OnReceiveCompleted);

                this.StartListening(newQueue);

                LogUtility.LogInformation(String.Format(CultureInfo.InvariantCulture, "Message queue {0} recovered successfully.", newQueue.QueueName));

                queueRecovered = true;
            }
            catch (Exception ex)
            {
                LogUtility.LogError(String.Format(CultureInfo.InvariantCulture, "The following error occurred while trying to recover queue: {0} error: {1}", queue.QueueName, ex.Message));                
            }
        }           
    }

    public void StopListening(MessageQueue queue)
    {
        queue.ReceiveCompleted -= new ReceiveCompletedEventHandler(this.OnReceiveCompleted);            
    }
4

1 に答える 1

8

サービスの再起動の結果である例外を受け取ったら、古い を解放する必要がありMessageQueueます。つまり、ReceiveCompletedイベントの配線を外したり、 を破棄したりしますMessageQueue。その後、 の新しいインスタンスを作成し、新しいインスタンスでイベントに再度MessageQueue接続します。ReceiveCompletedMessageQueue

または、特定の間隔で新しいインスタンスを作成するポーリング メソッドを使用することもできますMessageQueue.Receive(TimeSpan)。その場合、メッセージを処理してMessageQueueインスタンスを破棄し、反復を再開します。

MessageQueue毎回再作成することで、ビルトイン リカバリが保証されます。MessageQueueまた、基礎となるキューの内部キャッシングにより、作成のオーバーヘッドは最小限に抑えられます。

擬似コード...

while (!notDone)// or use a timer or periodic task of some sort...
{
    try
    {
        using (MessageQueue queue = new MessageQueue(queuePath))
        {
            Message message = queue.Receive(TimeSpan.FromMilliseconds(500));

            // process message
        }
    }
    catch (MessageQueueException ex)
    {
        // handle exceptions
    }
}
于 2012-04-26T18:24:43.983 に答える