Kiedy należy używać GC.SuppressFinalize()?

W. NET, w jakich okolicznościach powinienem używać GC.SuppressFinalize()?

Jakie korzyści daje mi użycie tej metody?

Author: GEOCHET, 2008-09-29

5 answers

SuppressFinalize powinien być wywoływany tylko przez klasę, która ma finalizer. Informuje Garbage Collector (GC), że obiekt został całkowicie wyczyszczony.

Zalecany wzór IDisposable Gdy masz finalizer to:

public class MyClass : IDisposable
{
    private bool disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // called via myClass.Dispose(). 
                // OK to use any private object references
            }
            // Release unmanaged resources.
            // Set large fields to null.                
            disposed = true;
        }
    }

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

    ~MyClass() // the finalizer
    {
        Dispose(false);
    }
}

Zwykle CLR przechowuje Zakładki na obiektach z finalizerem podczas ich tworzenia (co powoduje, że ich tworzenie jest droższe). SuppressFinalize informuje GC, że obiekt został prawidłowo wyczyszczony i nie musi wchodzić do kolejki finalizera. Wygląda jak C++ Destruktor, ale nie zachowuje się jak jeden.

Optymalizacja SuppressFinalize nie jest trywialna, ponieważ twoje obiekty mogą długo czekać w kolejce finalizera. Nie daj się skusić, aby wywoływać SuppressFinalize na inne przedmioty. To poważna wada.

Wytyczne projektowe informują nas, że finalizer nie jest konieczny, jeśli twój obiekt implementuje IDisposable, ale jeśli masz finalizer, powinieneś zaimplementować IDisposable, aby umożliwić deterministyczne oczyszczanie twojej klasy.

Większość czas, w którym powinieneś być w stanie uciec z IDisposable, aby oczyścić zasoby. Finalizer powinien być potrzebny tylko wtedy, gdy obiekt przechowuje niezarządzane zasoby i musisz zagwarantować, że zasoby te zostaną wyczyszczone.

Uwaga: czasami Programiści dodają finalizer do debugowania kompilacji własnych klas IDisposable w celu sprawdzenia, czy kod prawidłowo usunął obiekt IDisposable.

public void Dispose() // Implement IDisposable
{
    Dispose(true);
#if DEBUG
    GC.SuppressFinalize(this);
#endif
}

#if DEBUG
~MyClass() // the finalizer
{
    Dispose(false);
}
#endif
 317
Author: Robert Paulson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-07 13:46:55

SupressFinalize mówi systemowi, że każda praca w finalizatorze została już wykonana, więc finalizator nie musi być wywoływany. Z. NET docs:

Obiekty implementujące IDisposable interfejs może wywołać tę metodę z IDisposable.Usunąć uniemożliwić śmieciarzowi wywołuję obiekt.Finalizuj na obiekt, który go nie wymaga.

Ogólnie większość metod Dispose() powinna być w stanie wywołać GC.SupressFinalize(), ponieważ powinno posprzątać wszystko, co zostanie wyczyszczone w finalizatorze.

SupressFinalize jest po prostu czymś, co zapewnia optymalizację, która pozwala systemowi nie kłopotać się kolejkowaniem obiektu do wątku finalizera. Poprawnie napisany Dispose()/finalizer powinien działać poprawnie z wywołaniem do GC.SupressFinalize() lub bez niego.

 41
Author: Michael Burr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-07 13:51:48

Ta metoda musi być wywołana na Dispose metodzie obiektów, która implementuje IDisposable, w ten sposób GC nie wywoła finalizera innym razem, jeśli ktoś wywoła metodę Dispose.

Zobacz: GC.Metoda SuppressFinalize (Object) - Microsoft Docs

 1
Author: albertein,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-07 13:54:58
Dispose(true);
GC.SuppressFinalize(this);

Jeśli obiekt posiada finalizer,. NET umieszcza referencję w kolejce finalizacji.

Ponieważ mamy wywołanie Dispose(ture), wyczyści obiekt, więc nie potrzebujemy kolejki finalizacji do wykonania tego zadania.

Więc wywołaj GC.SuppressFinalize(this) Usuń odniesienie w kolejce finalizacji.

 1
Author: Max CHien,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-07 13:55:44

Jeśli klasa lub cokolwiek z niej pochodzi, może zawierać Ostatnie aktywne odniesienie do obiektu za pomocą finalizera, to GC.SuppressFinalize(this) LUB GC.KeepAlive(this) powinny być wywołane NA obiekcie po dowolnej operacji, na którą może mieć niekorzystny wpływ ten finalizer, zapewniając tym samym, że finalizer nie uruchomi się przed zakończeniem tej operacji.

Koszt GC.KeepAlive() i GC.SuppressFinalize(this) są zasadniczo takie same w każdej klasie, która nie ma finalizera, A klasy, które mają finalizery, powinny ogólnie wywoływać GC.SuppressFinalize(this), więc używanie tej ostatniej funkcji jako ostatniego kroku Dispose() może nie zawsze być konieczne, ale nie będzie błędne.

 0
Author: supercat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-26 23:05:22