IDisposable Pattern. Как вызов моего финализатора избавиться от когда-либо свободных управляемых ресурсов? - PullRequest
0 голосов
/ 12 апреля 2019

У меня есть класс A, который реализует шаблон Disposable для освобождения неуправляемых ресурсов, таких как отмена подписки на события.Класс B использует класс A, но не оборачивает его в блок using {..}, и вызов explicity не вызывает A.Dispose (true), поэтому A.dispose вызывается в финализаторе A через стандартный вызов Dispose (false).Но затем, установив для параметра bool значение false, неуправляемые ресурсы не будут очищаться, то есть не отписываться от подписанных событий.Разве финализатор не должен вызывать Dispose (true) или класс B должен явно вызывать A.Dispose (true) в какой-то момент, например, в своем собственном финализаторе?

private bool _disposed = false; // To detect redundant calls

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                _promotionsSQLTableDependency.Stop();
                _awardsSQLTableDependency.Stop();
                _progressiveGeneratorService.OnProgressiveLevelsUpdate -= _progressiveUpdateHandler;
            }

            _disposed = true;
        }
    }

    ~PromotionHandler()
    {
        Dispose(false);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

Ответы [ 2 ]

2 голосов
/ 12 апреля 2019

реализует шаблон Disposable для освобождения неуправляемых ресурсов, таких как отмена подписки на события.

Отмена подписки на событие не является неуправляемым ресурсом, который необходимо очистить.

Класс B использует класс A, но не заключает его в блок {..} и вызовы explicity A.Dispose (true)

Это следует рассматривать какошибка в вашей программе.Весь смысл реализации IDisposable состоит в том, что этот объект должен быть явно очищен с помощью владельца (-ей) и завершен с ним.

Но затем, установив для параметра bool значение false, неуправляемыйресурсы не будут очищены,

Но это не неуправляемые ресурсы, поэтому они не очищаются в блоке finally.

Не следуетфинализатор вызывает Dispose (true) или класс B должен явно вызывать A.Dispose (true) в какой-то момент, например, в своем собственном финализаторе?

No.Вы не должны взаимодействовать с управляемыми объектами в финализаторе.Это небезопасно.Поскольку у вас нет неуправляемых ресурсов для очистки в финализаторе, вы даже не должны иметь финализатор.

0 голосов
/ 12 апреля 2019

Метод dispose должен использовать только параметр распоряжения, чтобы решить, освобождать ли управляемые ресурсы.Неуправляемые ресурсы всегда должны быть освобождены.

protected virtual void Dispose(bool disposing)
{
    if (!_disposed)
    {
        if (disposing)
        {
            // Free managed resources
        }

        // always free unmanaged resources

        _disposed = true;
    }
}

если вызов Dispose происходит через сборщик мусора (= через вызов Finalizer), а удаление имеет значение false, вам не нужно освобождать управляемые ресурсы.Сборщик мусора также вызовет финализатор этих управляемых объектов (возможно, даже раньше).

Это то, что документация говорит :

Во второй перегрузкепараметр распоряжения - это логическое значение, указывающее, поступает ли вызов метода из метода Dispose (его значение равно true) или из финализатора (его значение равно false).

Тело метода состоит из двух блоков.кода:

  • Блок, освобождающий неуправляемые ресурсы.Этот блок выполняется независимо от значения параметра размещения.

  • Условный блок, освобождающий управляемые ресурсы.Этот блок выполняется, если значение распоряжения истинно.Управляемые ресурсы, которые он освобождает, могут включать:

Управляемые объекты, которые реализуют IDisposable .Условный блок может использоваться для вызова их реализации Dispose.Если вы использовали безопасный дескриптор для переноса неуправляемого ресурса, вам следует вызвать здесь реализацию SafeHandle.Dispose (Boolean).

Управляемые объекты, которые занимают большие объемы памяти или потребляют ограниченные ресурсы ,Явное освобождение этих объектов в методе Dispose освобождает их быстрее, чем если бы они были недетерминированно возвращены сборщиком мусора.

Если вызов метода происходит из финализатора (то есть, если удаление имеет значение false), тольковыполняется код, который освобождает неуправляемые ресурсы.Поскольку порядок, в котором сборщик мусора уничтожает управляемые объекты во время финализации, не определен, вызов этой перегрузки Dispose со значением false не позволяет финализатору попытаться освободить управляемые ресурсы, которые, возможно, уже были освобождены.

...