Вопрос

У меня есть следующий код:

public void Dispose()
{
    if (_instance != null)
    {
        _instance = null;
        // Call GC.SupressFinalize to take this object off the finalization
        // queue and prevent finalization code for this object from
        // executing a second time.
        GC.SuppressFinalize(this);
    }
}

Хотя есть комментарий, который объясняет цель этого звонка, связанного с GC, я до сих пор не понимаю, почему он там.

Разве объект не предназначен для сборки мусора, когда все экземпляры прекращаются от существования, как, например, при использовании в using блокировать?

Что такое сценарий случая использования, где это будет играть важную роль?

Это было полезно?

Решение

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

Чтобы предотвратить пробежку метода убытки в два раза (если объект уже был утилизирован), вы добавляете GC.SuppressFinalize(this);. Отказ Документация обеспечивает образец:

class MyResource : IDisposable
{
    [...]

    // This destructor will run only if the Dispose method 
    // does not get called.
    ~MyResource()      
    {
        // Do not re-create Dispose clean-up code here.
        // Calling Dispose(false) is optimal in terms of
        // readability and maintainability.
        Dispose(false);
    }

    // Implement IDisposable.
    // Do not make this method virtual.
    // A derived class should not be able to override this method.
    public void Dispose()
    {
        Dispose(true);
        // This object will be cleaned up by the Dispose method.
        // Therefore, you should call GC.SupressFinalize to
        // take this object off the finalization queue 
        // and prevent finalization code for this object
        // from executing a second time.
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        // Check to see if Dispose has already been called.
        if(!this.disposed)
        {
            // If disposing equals true, dispose all managed 
            // and unmanaged resources.
            if(disposing)
            {
                // Dispose managed resources.
                component.Dispose();
            }

            // Call the appropriate methods to clean up 
            // unmanaged resources here.
            resource.Cleanup()          
        }
        disposed = true;         
    }
}

Другие советы

Вывоз мусора: GC восстанавливает память, используемую объектом, когда объект не будет ссылаться.

Утилизировать: Метод от интерфейса IDSPosable, который должен выпустить все управляемые и неуправляемые ресурсы, когда программист вызывает его (прямо или косвенно через блок с использованием).

Финализатор: метод освобождения всех неуправляемых ресурсов. Вызывается GC, прежде чем восстановить память.

Управляемый ресурс: любой класс .NET, который реализует IDisposable Интерфейс, как потоки и DBConnections.

Неуправляемый ресурс: начинка, завернутая в управляемые ресурсные классы. Ручки Windows являются наиболее тривиальными примерами.


Теперь, чтобы ответить на ваш вопрос:

GC сохраняет список (очередь доработки) всех объектов, класс которого объявляет финализатор (~ ClassName в C #). Объекты помещаются в эту очередь при создании. GC периодически проходит, чтобы проверить, есть ли какие-либо объекты недоступны из программы. Затем он проверяет, есть ли какие-либо недоступные объекты в очереди окончательной очереди и помещают их в другую очередь, называемую предварительной очередью, в то время как остальные являются восстановленными. Отдельная нить используется для запуска методов завершения доработки объектов в предварительной очереди.

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

То SuppressFinalize Метод просто устанавливает флаг в заголовке объекта, который указывает, что финализатор не должен работать. Таким образом, GC может легко восстановить память об объекте. Согласно определению выше, Dispose Способ делает то же самое, что и финализатор (и более), поэтому, если оно выполняется, то доработка больше не нужно. С использованием SuppressFinalize Метод, вы можете сохранить некоторую работу для GC, уведомив его об этом факте. Кроме того, теперь вам не нужно реализовывать проверки в финализаторе, чтобы избежать двойного выпуска. Единственная проблема с Dispose Это не гарантированно запускать, потому что это ответственность программиста, поэтому иногда нам нужно беспокоить финализаторы.


Это, как говорят, это всего лишь очень редко, что вам нужно написать финализатор, потому что для подавляющего большинства обычных неуправляемых ресурсов уже существует управляемая обертка, и управляемые ресурсы должны быть освобождены, позвонив их Dispose методы от вашего собственного Dispose Метод, а оттуда только! В финализаторах вы никогда не должны вызывать метод урва.


дальнейшее чтение:

Объекты, которые могут быть доработаны, выдержаны первым запуском GC.

Обычно, когда GC обнаруживает, что объект недоступен, то он его восстанавливает. Если объект будет окончательно, то ГХ не восстанавливает его; Вместо этого он считает, что он несмотря на то, что все объекты, которые этот объект ссылки и т. Д.), и расплачивает его для завершения завершения. Объект будет восстановлен только тогда, когда он нашел опять таки быть недоступным в какой-то момент после того, как он был доработан.

Это означает, что дорабатываемый объект несет дополнительную стоимость: объект должен храниться в памяти в течение более длительного времени. Следовательно, вызов вы видите: стоит подавить финализацию, когда она не нужна. Здесь объект использует финализацию, чтобы гарантировать, что она всегда «утилизируется» в какой-то момент. Когда он располагается явно, он больше не должен быть завершен.

Если ваш тип реализует финализатор (~MyType() { }), он держит сборщик мусора от него. Используется, когда ваш финаризер заботится о неуправляемых типах, но пользователь уже звонил Dispose() (явно или через using() { } Блок), освобождая эти неуправляемые типы.

От MSDN: Gc.cuppressfinalize.:

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

Объекты, которые реализуют интерфейс IDisPosable, могут вызвать этот метод от IDSPOLABLABLABLABLABLABLABLABLE .. ::. Утилизируйте метод для предотвращения вызовов мусора отзывающего объекта .. ::. Доработка на объекте, который не требует этого.

Обычно вы будете использовать это, если ваш объект не ссылается на другие объекты, просто дискретные типы или уже сбрасывают любые ссылки на объекты NULL.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top