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?
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
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.
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
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.
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.
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