【问题标题】:C# BlockingCollection Dispose methodC# BlockingCollection 处置方法
【发布时间】:2019-05-24 07:26:26
【问题描述】:

BlockingCollection<T> 类的Documentation 有以下注释:

Always call Dispose before you release your last reference to the 
BlockingCollection<T>. Otherwise, the resources it is using will not be freed 
until the garbage collector calls the BlockingCollection<T> object's Finalize 
method.

而C#中BlockingCollection&lt;T&gt;internal implementation有如下方法:

/// <summary>
/// Releases resources used by the <see cref="T:System.Collections.Concurrent.BlockingCollection{T}"/> instance.
/// </summary>
/// <param name="disposing">Whether being disposed explicitly (true) or due to a finalizer (false).</param>
protected virtual void Dispose(bool disposing)

这个Dispose只有一次调用,参数disposing: true,调用后终止抑制。但是,令我惊讶的是,类中没有明确的终结器,甚至没有调用Dispose(false)。 看起来Dispose 函数相对简单,它只是删除了对不同对象的引用以加快 GC 速度。在这种情况下,当我们忘记显式调用Dispose() 时,GC 会为我们完成这项工作。

有人能发现这个类的内部结构吗?方法Dispose(bool disposing) 的目的是什么?即使在不需要的情况下,为 .NET 核心库实现此方法是否常见?

【问题讨论】:

  • 等待句柄不是免费的,您忽略了它在 dispose 方法中进行的 m_waitHandle.Dispose(); 调用。
  • 关于文档中的消息,我没有检查此类型上是否存在终结器,所以我会相信你的话,但这可能是复制粘贴的简单案例在某些文档中,我看到文档中的几种类型发布了完全相同的消息。
  • Dispose 的目的是处理等待句柄,您甚至链接到显示此内容的源代码,所以我不太确定您在这里问什么。
  • 这是dispose pattern 的变体。由于没有非托管资源,它被简化了,但继承的类可能包含非托管资源,因此需要完整的 dispose 模式实现,而基类通过实现这个虚拟方法提供了参与其中的可能性。
  • 我理解 Dispose() 方法在明确使用时的用途(并且我知道 Disposable 模式)。但是我很好奇没有明确调用Dispose() 的情况。看起来文档说在这种情况下Dispose() 将在最终确定阶段执行,Dispose(false) 方法的存在也看起来像是对这一假设的确认。但另一方面,没有明确的终结器,也没有调用Dispose(false) 方法。

标签: c# blockingcollection


【解决方案1】:

我认为关于如何正确实现 dispose 模式的 MSDN documentation 值得一读。但是,您的问题的答案是 BlockingCollection 不是密封的。这意味着它可以被导出。 void Dispose(bool disposing) 的原因是允许派生类正确地取消分配基类的资源。所以,例如,我可以实现

class Foo : BlockingCollection<string>
{
  private bool disposed = false;

  ~Foo()
  {
    Dispose(false);
  }

  protected override void Dispose(bool disposing)
  {
    if (disposed)
    {
      return;
    }

    if (disposing)
    {
      // free managed resources
    }

    // free unmanaged resources

    disposed = true;
    base.Dispose(disposing);
  }
}

通过这样做,当调用 Dispose() 时,BlockingCollection 将在 Foo 上调用 Dispose(true),最终将在 BlockingCollection 上调用 Dispose(true),您将获得抑制 ~Foo() 终结器的好处。如果Dispose() 方法没有被调用,终结器不会被抑制,它会被调用,允许Foo 仍然释放它的非托管资源。

【讨论】:

    猜你喜欢
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    • 2021-04-03
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 2015-12-09
    • 1970-01-01
    相关资源
    最近更新 更多