This post originated from an RSS feed registered with .NET Buzz
by Adrian Florea.
Original Post: Hurry up, Mr. Finalizer!
Feed Title: Web Log di Adrian Florea
Feed URL: /error.aspx?aspxerrorpath=/adrian/Rss.aspx
Feed Description: "You know you've achieved perfection in design, not when you have nothing more to add, but when you have nothing more to take away." Antoine de Saint-Exupery
Sperimentando in questi giorni delle cose, mi sono fermato su una prova che mi è apparsa piuttosto strana: il seguente snippet
using System; classFoo { staticint i = 0; ~Foo() { Foo f = newFoo(); Console.WriteLine(++i); } staticvoid Main() { Foo foo = newFoo(); } }
stampa a console numeri consecutivi e si ferma senza errore dopo qualche decina di migliaia!...
La spiegazione l'ho trovata solo adesso, dopo tante fantasie sognate, in una pagina (467) di Richter:
"Quando è in corso il regolare arresto di un processo," [...] "ciascun metodo Finalize ha circa 2 secondi di tempo per essere restituito. Se un metodo Finalize non viene restituito entro 2 secondi, CLR interromperà il processo e non saranno richiamati altri metodi Finalize. Inoltre, se per chiamare i metodi Finalize di tutti gli oggetti si superano i 40 secondi, allora di nuovo, CLR interromperà il processo.
Il codice in un metodo Finalize può costruire nuovi oggetti. Se questa operazione si verifica nel corso dell'arresto di CLR, CLR continuerà a raccogliere gli oggetti e a richiamare i relativi metodi Finalize fino a quando non vi saranno più oggetti o fino alla scadenza dei 40 secondi.
Nota. Questi valori di timeout erano corretti al momento in cui è stato scritto il testo; è possibile vengano modificati da Microsoft in futuro."
I numeri vengono stampati dallo snippet in meno di 40 secondi, ma non il valore del timeout è importante, bensì l'idea. Per esempio, con un valore di 3000 milisecondi passato al metodo Sleep questo snippet:
using System; using System.Threading; classFoo { ~Foo() { Thread.Sleep(3000); Console.WriteLine("Ciao"); } staticvoid Main() { Foo foo = newFoo(); } }
non stampa nulla a console, mentre con un valore di 1000 milisecondi viene stampato Ciao (ho scelto due valori intorno ai 2 secondi, uno maggiore e l'altro minore).
Attenzione quindi ai tempi di esecuzione dei finalizer!