根据文件:"SemaphoreSlim不使用Windows内核信号量"。SemaphoreSlim是否使用了任何特殊资源,使得在不再使用SemaphoreSlim时调用Dispose变得非常重要?
SemaphoreSlim
Dispose
tct7dpnv1#
如果访问AvailableWaitHandle属性,则选择Yes,则必须调用Dispose()来清除非托管资源。如果您不访问AvailableWaitHandle,则否,调用Dispose()不会执行任何重要操作。如果您访问AvailableWaitHandle,SemaphoreSlim将按需创建ManualResetEvent。这可能很有用,例如,如果您需要等待多个句柄。如果您确实访问了AvailableWaitHandle属性,然后未能调用Dispose(),则ManualResetEvent将泄漏。这可能 Package 了一个指向非托管CreateEvent资源的句柄,该资源需要对CloseHandle的相应调用来清除。正如其他人所指出的,当您处理完任何实现IDisposable的对象时,您应该调用Dispose()。在这种情况下,忽略这种做法有几个风险,即使这样做在技术上可能是安全的:1.我的声明基于.NET 4.6.1的参考源代码。框架的某些未来版本将SemaphoreSlim更改为需要Dispose()的地方,这种可能性很小(双关语)。1.如果SemaphoreSlim在类外部公开,则调用代码可能会引用AvailableWaitHandle属性,而没有意识到类没有释放SemaphoreSlim,从而导致非托管资源泄漏。
AvailableWaitHandle
Dispose()
ManualResetEvent
CreateEvent
CloseHandle
IDisposable
zbdgwd5y2#
是的。它可能使用ManualResetEvent,而SafeWaitHandle使用的是SafeHandle,并且具有非托管句柄。您可以在此处的参考源中看到它。SafeHandle是可终结的,所以如果你不释放它(通过释放SemaphoreSlim),它将转到终结器,终结器将需要为你做这件事。由于终结器是一个单线程,它可能会在某些情况下过度工作,所以建议总是释放可终结的对象。
SafeWaitHandle
SafeHandle
crcmnpdw3#
对于许多其他的类,我同意i3arnon,但是对于SemaphoreSlim,我同意Tim的意见。如果你在一个低级类中使用SemaphoreSlim,并且不得不释放它,那么实际上你程序中的所有东西都将变成IDisposable,而实际上这是不必要的。考虑到AvailableWaitHandle是非常专门化的,通常不使用它,这就更正确了。为了防止其他程序员访问AvailableWaitHandle,你可以将它 Package 在一个不可释放的类中,例如,你可以在Cleary和Hanselman的 Package 器中看到这一点,这两个 Package 器都基于Stephen Toub的帖子(顺便说一句,没有Dispose)。P.S.至于IDisposable契约,应该在文档中指定只有在访问AvailableWaitHandle时才需要Dispose。
wwodge7n4#
你应该总是在任何实现IDisposable的类上调用Dispose()(或者把它放在using语句中),而不是根据它的内部实现来做决定。类的作者已经通过实现IDisposable接口为你做了这个决定。
using
4条答案
按热度按时间tct7dpnv1#
如果访问
AvailableWaitHandle
属性,则选择Yes,则必须调用Dispose()
来清除非托管资源。如果您不访问
AvailableWaitHandle
,则否,调用Dispose()
不会执行任何重要操作。如果您访问
AvailableWaitHandle
,SemaphoreSlim
将按需创建ManualResetEvent
。这可能很有用,例如,如果您需要等待多个句柄。如果您确实访问了AvailableWaitHandle
属性,然后未能调用Dispose()
,则ManualResetEvent
将泄漏。这可能 Package 了一个指向非托管CreateEvent
资源的句柄,该资源需要对CloseHandle
的相应调用来清除。正如其他人所指出的,当您处理完任何实现
IDisposable
的对象时,您应该调用Dispose()
。在这种情况下,忽略这种做法有几个风险,即使这样做在技术上可能是安全的:1.我的声明基于.NET 4.6.1的参考源代码。框架的某些未来版本将
SemaphoreSlim
更改为需要Dispose()
的地方,这种可能性很小(双关语)。1.如果
SemaphoreSlim
在类外部公开,则调用代码可能会引用AvailableWaitHandle
属性,而没有意识到类没有释放SemaphoreSlim
,从而导致非托管资源泄漏。zbdgwd5y2#
是的。
它可能使用
ManualResetEvent
,而SafeWaitHandle
使用的是SafeHandle
,并且具有非托管句柄。您可以在此处的参考源中看到它。
SafeHandle
是可终结的,所以如果你不释放它(通过释放SemaphoreSlim
),它将转到终结器,终结器将需要为你做这件事。由于终结器是一个单线程,它可能会在某些情况下过度工作,所以建议总是释放可终结的对象。crcmnpdw3#
对于许多其他的类,我同意i3arnon,但是对于SemaphoreSlim,我同意Tim的意见。如果你在一个低级类中使用SemaphoreSlim,并且不得不释放它,那么实际上你程序中的所有东西都将变成IDisposable,而实际上这是不必要的。考虑到AvailableWaitHandle是非常专门化的,通常不使用它,这就更正确了。
为了防止其他程序员访问AvailableWaitHandle,你可以将它 Package 在一个不可释放的类中,例如,你可以在Cleary和Hanselman的 Package 器中看到这一点,这两个 Package 器都基于Stephen Toub的帖子(顺便说一句,没有Dispose)。
P.S.至于IDisposable契约,应该在文档中指定只有在访问AvailableWaitHandle时才需要Dispose。
wwodge7n4#
你应该总是在任何实现
IDisposable
的类上调用Dispose()
(或者把它放在using
语句中),而不是根据它的内部实现来做决定。类的作者已经通过实现IDisposable
接口为你做了这个决定。