私はBeginReceive()、EndReceive()、およびReceivedCompletedイベントを使用している非同期APIサポートを使用してMSMQから読み取っているコードを持っています。基本的なパターンは、新しいメッセージを待っている(私が見ることができる問題は保留BeginReceiveは(常に存在することであるMessageQueue.ReceiveCompleted Event ...MSMQリスナを正しくクリーンアップする方法は?
void StartListening()
{
_msgQ.ReceiveCompleted += ReceiveCompletedEventHandler(FooReceiveCompleted);
_msgQ.BeginReceive();
}
void FooReceiveCompleted(Object source, ReceiveCompletedEventArgs asyncResult)
{
Message msg = _msgQ.EndReceive();
// Do stuff with message.
// Set up listening for next message.
_msgQ.BeginReceive();
}
void StopListening()
{
_msgQ.Close();
}
から取られた)である、と.NETのドキュメントを読んで、そこを通って表示されません。
メッセージを受信せずにEndReceive()を呼び出すと、メッセージが利用可能になるまで呼び出しがブロックされます。 )は、EnableConnectionCacheがfalseに設定されていない限り、MSMQ(したがって保留中のリスナー)の基になるハンドルをクリーンアップしません。そうでない場合、ハンドルはキャッシュされ、クリーンアップされません閉じるための呼び出しで。私はこれを行うことができますが、理想的にはキャッシングを使いたいと思います。
私が見ることのできる唯一の他のオプションは、キャッシングを有効にして静的メソッドMessageQueue.ClearConnectionCache()を呼び出すことでした。おそらくアプリケーションドメイン全体であり、したがって、閉じようとしているキューに関係のないキューに影響します。
補遺: 追加オプション(MessageQueue.Close()から)、彼らが共有される可能性がありますので...
閉じるには、常に読み取りを解放し、キュー、 にハンドルを書き込みません。 のいずれかの手順を実行して、Closeが読み取りと書き込みのハンドルをキューに解放するようにすることができます。
排他アクセスでMessageQueueを作成します。これを行うには、 MessageQueue(String、Boolean)またはMessageQueue(String、Boolean、Boolean、 Boolean)コンストラクターを呼び出し、sharedModeDenyReceiveパラメーターを に設定します。
接続キャッシュを無効にしてMessageQueueを作成します。これを行うには、 MessageQueue(String、Boolean、Boolean)コンストラクターを呼び出し、 enableConnectionCacheパラメーターをfalseに設定します。
接続キャッシュを無効にします。これを行うには、EnableConnectionCache プロパティをfalseに設定します。
したがってドキュメントからAPIの私の第一印象は、(BeginReceive/EndReceiveを使用した場合)キャッシングがまたはあなたがキューへの排他的アクセスを持って使用されていない場合を除き、あなたが適切にキューを終了することができないということです。
ReceivedCompleted()呼び出しの理由がEndReceive()の呼び出しとタイムアウト例外のキャッチ以外のタイムアウトであることを検出する方法はありますか? – NTDLS