2013-06-07 20 views
6

Właśnie natknąłem się na niektóre kod, który używa metody GC.KeepAlive() i staram się zrozumieć, jak to działa. Na przykład w ten kod:W jaki sposób metoda KeepAlive Garbage Collector działa z timerem?

Timer timer = new System.Timers.Timer(5000); 
timer.Elapsed += new ElapsedEventHandler(OnTimedEvent); 
timer.Enabled = true; 
GC.KeepAlive(timer); 

W tym kodzie mój zrozumienia jest to, że obiekt Timer jest tworzony, który spawns wątek, który kursuje co 5 sekund. Następnie uruchamiana jest linia GC. Następnie metoda kończy działanie, niszcząc licznik czasu, gdy działa usuwanie śmieci.

KeepAlive utrzymuje go przy życiu tylko przed wywołaniem KeepAlive, co dla mnie wygląda na około 0,0000001 sekund i nie zostanie tam zniszczony, ponieważ istnieje lokalne odniesienie do niego (chyba że go niszczy, ponieważ nic indziej dzieje się z obiektem z timerem?)

Tak czy inaczej, zanim trafi 5000, metoda zakończy się wieki temu i bardzo prawdopodobne jest, że zegar zostanie zniszczony. Jaki jest cel tej linii?

+1

Zapytaj oryginalnego programistę? – dtb

+0

Tak długo, jak masz do czynienia z kodem zarządzanym (tj. W całości z .Net), nie ma potrzeby używania 'GC.KeepAlive'. Wszystko, co robi, to zachować odniesienie do obiektu licznika czasu, aby nie zostały zebrane śmieci. [Dokumenty] (http://msdn.microsoft.com/en-us/library/system.gc.keepalive.aspx) twierdzą, że naprawdę jest przeznaczony do użytku z obiektami przydzielonymi w zarządzanym kodzie, które są przekazywane do niezarządzanego kodu (np. wywołanie Win32 API). Tak więc dla tego konkretnego przykładu wydaje się to bezcelowe. – ThatBlairGuy

+1

Niestety pierwotny programista dawno już minął i zostawił mi to piękno projektu do utrzymania :) – NibblyPig

Odpowiedz

4

Jaki jest cel tej linii?

Nic. Nie powinieneś go używać, ponieważ nic nie pomaga. Ten kod został prawdopodobnie napisany przez kogoś, kto nie jest szczególnie zaznajomiony z działaniem klasy Timer.

Wewnętrznie klasa Timer będzie używać całkowicie różnych środków, aby upewnić się, że nie są to śmieci zebrane, zanim powinny być. Aby uzyskać szczegółowe informacje, patrz this question.

+1

Również to: http://stackoverflow.com/questions/4959149/do-timer-object-get-gc-ed-when-no-other-object-references-them –

+0

Interesujące. Zastanawiam się, czy to prawda dla System.Timers.Timer (że OP używa) i System.Threading.Timer. Wydaje mi się, że przypominam sobie, że przynajmniej czasomierz wątku zostanie zebrany. Będzie musiał to zbadać. ... I odpowiedź na moje pytanie: http: // stackoverflow.com/q/4962172/56778 –

+1

@JimMischel Testowanie jest łatwe. Kilka przykładowych programów wskazało, że ani system.timers.timer, ani system.threading.timer nie zostaną zebrane podczas wykonywania. – Servy

1

W tym kontekście nie ma powodu dla tej linii. Jedyny czas może pomóc to, czy jest dużo kodu pomiędzy timer.Enabled i wywołaniu KeepAlive, jak w:

timer.Enabled = true; 
    // lots of code here that does 
    // things that take some time 
    GC.KeepAlive(timer); 
} 

To zapobiegnie śmieciarza ze zbierania timer przed zakończeniem metoda. Bez wywołania KeepAlive, GC może zdecydować, że timer nie jest już używany po ustawieniu Enabled i może wykonać wczesny odbiór.

Jeśli chcesz mieć stały licznik czasu, musisz zadeklarować go w zasięgu klasy.

+0

Jest to sprzeczne z Servy, które, jak przypuszczam, ma lepsze argumenty. Zauważcie, że z moich przyzwyczajeń, wszyscy liczą na poziomie klasy, chociaż mógłbym szybko wypróbować lokalną opcję, bez KeepAlive, która wydaje się przydatna tylko dla niezarządzanego kodu, który wciąż ma odniesienie i opóźnia finalizację. –

+0

@AndreasReiff: Odpowiedź Servy jest poprawna, jak wskazałem w moim komentarzu do jego pytania. Podałem również link do pytania, które zawiera bardzo szczegółową odpowiedź na to pytanie. –

Powiązane problemy