我有代碼是從MSMQ使用異步API支持讀取,即使用BeginReceive(),EndReceive()和ReceivedCompleted事件。基本模式(取自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();
}
我可以看到的問題是,總是有未決BeginReceive()等待新的消息,並通過讀取文檔的.Net似乎沒有一個作爲一個官方/推薦的方式來清理它,以便停止收聽
如果我在沒有消息接收的情況下調用EndReceive(),那麼調用將阻塞,直到消息變爲可用爲止。 )不會清除MSMQ上的底層句柄(因此也不會清除掛起的監聽器),除非EnableConnectionCache設置爲false,否則句柄將被緩存並且不會清理乾淨在通話結束。我可以做到這一點,但理想情況下我想使用緩存。
我能看到的唯一的其他選擇是啓用緩存,然後調用靜態方法MessageQueue.ClearConnectionCache(),它大概是應用程序域範圍,因此會影響與我正在嘗試關閉的隊列無關的隊列。
附錄: 附加選項(從MessageQueue.Close())...
關閉並不總是免費的讀取和寫入手柄到隊列, ,因爲他們可能被共享。您可以採取以下任一步驟 以確保Close將讀取和寫入句柄釋放到隊列中:
創建具有獨佔訪問權限的MessageQueue。要做到這一點,調用 的MessageQueue(字符串,布爾值)或的MessageQueue(字符串,布爾值, 布爾)構造函數和sharedModeDenyReceive參數設置爲 真。
創建禁用連接高速緩存中的MessageQueue。要做到這一點, 調用的MessageQueue(字符串,布爾值,布爾)構造函數,並設置 的enableConnectionCache參數設置爲false。
禁用連接緩存。爲此,請將EnableConnectionCache 屬性設置爲false。
因此我從文檔的API的第一印象是,你不能正確地終止隊列(使用BeginReceive/EndReceive時),除非緩存不使用或你必須排隊獨佔訪問。
如何檢測到ReceivedCompleted()調用的原因是除了調用EndReceive()並捕獲超時異常之外的超時? – NTDLS 2016-10-14 16:38:48