2011-03-15 42 views
2

我有一種情況,我創建了多個IDisposable對象,每個對象封裝了一個EventWaitHandle實例,以便我的應用程序的各個感興趣部分可以在其上等待。該實例不能直接訪問其所有者對象外的任何代碼。它只能通過包裝調用間接訪問。在發送信號後處理()EventWaitHandle是否安全?

一旦對象發出信號,它就不再有用,因此它由中央管理器對象處理並從其參考列表中拋棄。

現在的問題是,如何處理封裝的EventWaitHandle?當然,它也應該被處置,並且儘快,以防止我的應用程序泄漏操作系統句柄。

但是,在事件通過其擁有者對象發出信號後立即同步執行該操作是否安全?如果還有線程仍在等待釋放(即阻塞在WaitOne()的呼叫中),會發生什麼情況?

這裏推薦的方法是什麼?

+0

你確定當你發出信號時* *會等待事件的所有線程是*當前*等待它嗎?或者有些線程可能在他們開始等待事件之前處於某個位置,但還沒有等待呢? – 2011-03-15 11:34:08

+0

@Lasse:好吧,當然,在多線程應用程序中可能會發生任何事情。 :)但就我的對象而言,它們的WaitOne()包裝器是原子的。它要麼進入等待,要麼立即返回。後者不是問題,前者是(或者至少可以是,在我看來)。 – aoven 2011-03-15 11:44:11

回答

0

我想是時候用我自己的發現來結束這一次。

我在文檔中找不到任何直接的指引,但決定遵循我從Raymond Chen的博客中提取的信息。在他的文章中(我忘記了確切的鏈接),他提到Win32 API規則規定事件的句柄在等待期間必須保持有效。在非託管世界,這意味着至少有一個事件處理必須保持開放。

AFAIU,.NET的實現在底層使用Win32 API,每個EventWaitHandle實例對應一個單獨的非託管事件。當EventWaitHandle.Dispose()關閉底層非託管事件的唯一句柄時,這會使事件實例無效。

簡而言之,正確的做法似乎是構建一個並行基礎結構,通過該基礎結構,事件發佈者可以通過該基礎結構通知潛在的偵聽器該事件即將消失。然後,發佈者必須等到所有聽衆都已「取消訂閱」(即停止等待),然後才能繼續Dispose()事件實例。

這是很多簿記,但最終,它似乎只是正確的。希望這有助於爲其他人清除一些事情。

相關問題