【问题标题】:Do I need to Dispose a SemaphoreSlim我需要处理 SemaphoreSlim
【发布时间】:2015-11-09 02:07:09
【问题描述】:

根据文档:

SemaphoreSlim 不使用 Windows 内核信号量”。

SemaphoreSlim 是否使用了任何特殊资源,这使得在不再使用 SemaphoreSlim 时调用 Dispose 很重要?

【问题讨论】:

  • 你可以自己查看source code here,但是给你一个强烈的提示是:它实现了IDisposable接口。
  • @Steve HttpClient 告诉我们要警惕盲目处置所有实现 IDisposable 的东西。
  • @user247702 我不同意这种说法,问题不在于处理HttpClient,否则您将为每条 HTTP 消息创建一个新实例,这会阻止您利用重用连接。

标签: c# .net semaphore dispose idisposable


【解决方案1】:

如果您访问AvailableWaitHandle 属性,然后是,您必须调用Dispose() 来清理非托管资源。

如果您不访问AvailableWaitHandle然后否,调用Dispose() 不会做任何重要的事情。

如果您访问AvailableWaitHandleSemaphoreSlim 将按需创建ManualResetEvent。这可能很有用,例如,如果您需要等待多个句柄。如果您确实访问了AvailableWaitHandle 属性,然后未能调用Dispose(),您将有一个泄漏的ManualResetEvent,它可能包装了一个非托管CreateEvent 资源的句柄,该资源需要相应地调用CloseHandle 来清理起来。

正如其他发帖者所指出的,当您完成任何实现IDisposable 的对象时,您应该调用Dispose()。在这种情况下,忽略这种做法会带来一些风险,即使在技术上这样做可能是安全的:

  1. 我的陈述基于 .NET 4.6.1 的参考源代码。框架的某些未来版本将SemaphoreSlim 更改为需要Dispose() 的位置总是存在微小(双关语)的可能性。
  2. 如果您的SemaphoreSlim 暴露在您的类之外,调用代码可能会引用AvailableWaitHandle 属性,而没有意识到您的类没有处理SemaphoreSlim 并造成非托管资源泄漏。

【讨论】:

    【解决方案2】:

    是的。

    它可能使用ManualResetEvent,它使用SafeWaitHandle,这是一个SafeHandle,它有一个非托管句柄。

    你可以在reference source here看到它。

    SafeHandle 是可终结的,因此如果您不处置它(通过处置SemaphoreSlim),它将转到需要为您执行此操作的终结器。由于终结器是单线程,因此在某些情况下可能会过度工作,因此始终建议处置可终结对象。

    【讨论】:

      【解决方案3】:

      您应该始终在任何实现IDisposable 的类上调用Dispose()(或将其放在using 语句中),而不是根据其内部实现做出决定。类作者已经通过实现IDisposable 接口为您做出了决定。

      【讨论】:

      • 这确实是一般规则。我的问题专门针对 SemaphoreSlim。请注意,SemaphoreSlim 用例通常不会将它们用于使用“使用”。
      • 实施IDisposable 的决定可能并不总是由课程作者决定。有许多接口,例如IEnumerator<T>,它们继承IDisposable,以允许一些实现在使用后需要清理。即使实现IEnumerable<T> 的类的合同规定其特定的GetEnumerator 实现将始终返回一个可以安全放弃的对象,IEnumerable<T>.GetEnumerator 返回的任何对象都必须实现IDisposable,无论它是否需要清理。
      【解决方案4】:

      对于许多其他课程,我会同意 i3arnon,但对于 SemaphoreSlim,我会同意 Tim 的评论。如果您在低级类中使用 SemaphoreSlim 并且必须处理它,那么实际上您程序中的所有内容都将变为 IDisposable,而实际上它不是必需的。鉴于 AvailableWaitHandle 非常专业并且通常不被使用,这一点就更真实了。

      为了防止其他编码人员访问 AvailableWaitHandle,您可以将其包装在非一次性类中。例如,您可以在 Cleary 和 Hanselman 的包装器中看到这一点,它们都基于 Stephen Toub 的帖子(顺便说一下,它没有 Dispose)。

      附:至于 IDisposable 合约,应该只在文档中指定 Dispose 仅​​在访问 AvailableWaitHandle 时才需要。

      【讨论】:

        猜你喜欢
        • 2011-02-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多