0

Windows Server 2003 で実行されている C# ASP.NET 3.5 Web アプリケーションで、次のエラーが発生することがあります。

"Object reference not set to an instance of an object.:   at System.Messaging.Interop.MessagePropertyVariants.Unlock()
   at System.Messaging.Message.Unlock()
   at System.Messaging.MessageQueue.ReceiveCurrent(TimeSpan timeout, Int32 action, CursorHandle cursor, MessagePropertyFilter filter, MessageQueueTransaction internalTransaction, MessageQueueTransactionType transactionType)
   at System.Messaging.MessageEnumerator.get_Current()
   at System.Messaging.MessageQueue.GetAllMessages()".

このエラーをスローするコード行は次のとおりです。

Message[] msgs = Global.getOutputQueue(mode).GetAllMessages();

ここでGlobal.getOutputQueue(mode)、メッセージを取得したいメッセージキューを指定します。

アップデート:

 Global.getPool(mode).WaitOne();
 commonClass.log(-1, "Acquired pool: " + mode, "Report ID: " + unique_report_id);
            ............../* some code /
            ..............
                        lock(getLock(mode))
                        {
                            bool yet_to_get = true;
                            int num_retry = 0;
                            do
                            {
                                try
                                {
                                    msgs = Global.getOutputQueue(mode).GetAllMessages();
                                    yet_to_get = false;
                                }
                                catch
                                {
                                    Global.setOutputQueue(mode);
                                    msgs = Global.getOutputQueue(mode).GetAllMessages();
                                    yet_to_get = false;
                                }
                                ++num_retry;
                            }
                            while (yet_to_get && num_retry < 2);
                        }
... / some code*/
....
finally
            {
                commonClass.log(-1, "Released pool: " + mode, "Report ID: " + unique_report_id);
                Global.getPool(mode).Release();
            }
 

4

2 に答える 2

1

これは古いスレッドですが、Google が私をここに連れてきたので、調査結果を追加します。

これはタイミングの問題であるというユーザー: tallseth に同意します。

メッセージ キューが作成された後、すぐに使用できるわけではありません。

        try
        {
            return _queue.GetAllMessages().Length;
        }
        catch (Exception)
        {
            System.Threading.Thread.Sleep(4000);
            return _queue.GetAllMessages().Length;
        }

作成されたことがわかっているキューにアクセスするときに例外をキャッチする場合は、一時停止を追加してみてください。

関連するメモ

_logQueuePath = logQueuePath.StartsWith(@".\") ? logQueuePath : @".\" + logQueuePath;
 _queue = new MessageQueue(_logQueuePath);
 MessageQueue.Create(_logQueuePath);
 bool exists = MessageQueue.Exists(_logQueuePath); 

MessageQueue.Exists(文字列 nameofQ) を実行しています。キューを作成した直後のメソッドは false を返します。したがって、次のようなコードを呼び出すときは注意してください。

        public void CreateQueue()
    {
        if (!MessageQueue.Exists(_logQueuePath))
        {
            MessageQueue.Create(_logQueuePath);
        }
    }

作成しようとしているキューが既に存在することを示す例外がスローされる可能性があるためです。

-編集:(この新しい情報に関連するリンクがなくてすみません)

新しく作成された MessageQueue は、少なくとも 1 つのメッセージを受信するまで MessageQueue.Exists(QueuePath) で false を返すことを読みました。

これと前述のポイントを念頭に置いておくことで、コードが確実に実行されるようになりました。

于 2014-05-23T03:17:48.633 に答える
1

あなたの説明とこのスレッドは、タイミングの問題を示唆しています。私はMessageQueueオブジェクトをめったに作成せず (おそらく 1 回だけ) Global.getOutputQueue(mode)、キャッシュされたバージョンを返しましたが、これを回避する可能性が高いようです。

編集: 詳細は、反対の問題があることを示唆しています。メッセージ キューへのアクセスをカプセル化し、この例外をキャッチして、その例外が発生した場合はキューを再作成することをお勧めします。したがって、Global.getOutputQueue(mode).GetAllMessages() への呼び出しを次のように置き換えます。

public void getAllOutputQueueMessages()
{
    try
    {
        return queue_.GetAllMessages();
    }
    catch (Exception)
    {
        queue_ = OpenQueue();
        return queue_.GetAllMessages();
    }
}

機能を保持していないことに気付くでしょうmodeが、アイデアはわかります。もちろん、キューに対して行う他の呼び出しに対してこのパターンを複製する必要がありますが、(キュー インターフェイス全体ではなく) 行う呼び出しに対してのみ複製する必要があります。

于 2012-07-05T18:13:23.797 に答える