2015-08-16 48 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。