C # BlockingCollection метод Dispose - PullRequest
0 голосов
/ 23 мая 2019

Документация класса BlockingCollection<T> имеет следующее примечание:

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.

И внутренняя реализация из BlockingCollection<T> в C # имеет следующий метод:

/// <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. В этом случае GC сделает эту работу за нас, если мы забудем явно вызвать Dispose().

Может ли кто-нибудь заметить свет на внутренностях этого класса? Какова цель метода Dispose(bool disposing)? Является ли обычной практикой применение этого метода для основных библиотек .NET даже в тех случаях, когда он не нужен?

1 Ответ

2 голосов
/ 24 мая 2019

Я думаю, что документация MSDN о том, как правильно реализовать шаблон удаления, стоит прочитать. Однако ответ на ваш вопрос заключается в том, что 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 вызовет Dispose(true) для Foo, что в итоге вызовет Dispose(true) для BlockingCollection, и вы получите преимущество, заключающееся в том, что финализатор ~ Foo () подавлен. Если метод Dispose() не вызывается, финализатор не подавляется и вызывается, что позволяет Foo по-прежнему освобождать свои неуправляемые ресурсы.

...