2015-08-16 60 views
10

根據文檔:我需要配置一個SemaphoreSlim

「一SemaphoreSlim不使用Windows內核信號」。

是否有使用的SemaphoreSlim這使得它重要的是要調用DisposeSemaphoreSlim將不再使用任何特殊的資源?

+0

你可以自己查看這裏的[源代碼](http://referencesource.microsoft.com/#mscorlib/system/threading/SemaphoreSlim.cs,d57f52e0341a581f),但對你的強烈暗示是:它實現IDisposable接口。 – Steve

回答

6

是的。

它可能使用ManualResetEvent,它使用SafeWaitHandle這是一個SafeHandle並且它有一個非託管句柄。

你可以在reference source here看到它。

SafeHandle是可定版的,所以如果你不處理它(通過處置SemaphoreSlim),它會去終結者,這將需要爲你做。由於終結器是一個單一的線程,它可能會在某些情況下過度勞累,所以總是建議處理可終結對象。

2

您應該始終致電Dispose()執行IDisposable的任何類(或將其放入using聲明中),而不是將您的決定建立在其內部實現的基礎上。班級作者已通過實施IDisposable界面爲您做出決定。

+0

這確實是一般規則。我的問題具體是關於SemaphoreSlim。請注意,SemaphoreSlim用例通常不會將它們借給「使用」。 –

+2

實現'IDisposable'的決定可能並不總是與類作者一樣。有許多接口,例如'IEnumerator ',它們繼承'IDisposable',以便在使用後需要清理一些*實現。即使實現「IEnumerable 」的類的合同要指定其特定實現的「GetEnumerator」將始終返回可安全放棄的對象,那麼由「IEnumerable .GetEnumerator」返回的任何對象都必須實現「IDisposable」無論是否需要清理。 – supercat

9

如果您訪問AvailableWaitHandle屬性,則是是,則必須調用Dispose()來清理非託管資源。

如果你不訪問AvailableWaitHandle,然後沒有,調用Dispose()將不會做任何重要的事情。

如果您訪問AvailableWaitHandle,SemaphoreSlim將按需創建ManualResetEvent。這可能是有用的,例如,如果您需要等待多個句柄。如果您訪問AvailableWaitHandle屬性,然後無法調用Dispose(),則會泄露ManualResetEvent,這可能會將句柄包裝爲需要對CloseHandle進行相應調用的非託管CreateEvent資源進行清理。

正如其他海報指出的那樣,當您完成任何實現IDisposable的對象時,您應該調用Dispose()。在這種情況下,忽略這種做法存在一些風險,儘管從技術上來說可能是安全的:

  1. 我的聲明基於.NET 4.6.1的參考源代碼。總有一些苗條(雙關語意)的可能性,即某些將來的框架版本會將SemaphoreSlim更改爲需要Dispose()的地方。
  2. 如果您的SemaphoreSlim暴露在您的類之外,調用代碼可能會引用AvailableWaitHandle屬性,而不會意識到您的類不處理SemaphoreSlim並創建非託管資源泄漏。
+0

這是非常有用的信息。謝謝! –

0

對於很多其他課程,我會同意i3arnon,但對於SemaphoreSlim,我會與Tim的評論一起去。如果您在底層類中使用SemaphoreSlim並且必須處理它,那麼實際上程序中的所有內容都將變爲IDisposable,而實際上它不是必需的。鑑於AvailableWaitHandle是相當專業的並且通常不被使用,所以這更加真實。

爲了防止其他編碼員訪問AvailableWaitHandle,您可以將其包裝在非一次性類中。例如,您可以在Cleary和Hanselman的封裝中看到這一點,兩者都基於Stephen Toub的一篇文章(順便說一句,不是Dispose)。

P.S.至於IDisposable協議,只應在文檔中指定只有在訪問AvailableWaitHandle時才需要Dispose。