In base a MSDN, un riferimento a System.Threading.Timer deve essere conservato altrimenti verrà raccolto automaticamente. Quindi, se corro questo codice, non scrivere alcun messaggio (che è il comportamento previsto):C# Timers and Garbage Collection
static void Main(string[] args)
{
RunTimer();
GC.Collect();
Console.ReadKey();
}
public static void RunTimer()
{
new Timer(s => Console.WriteLine("Hello"), null, TimeSpan.FromSeconds(1), TimeSpan.Zero);
}
Tuttavia, se modifico il codice un po 'memorizzando il timer in una variabile locale temporanea, essa sopravvive e scrive il messaggio:
public static void RunTimer()
{
var timer = new Timer(s => Console.WriteLine("Hello"));
timer.Change(TimeSpan.FromSeconds(1), TimeSpan.Zero);
}
Durante la raccolta dei rifiuti, non v'è apparentemente alcun modo come accedere il timer dalla radice o di oggetti statici. Quindi, per favore, puoi spiegare perché il timer sopravvive? Dove viene conservato il riferimento?
Questo certamente * usato * è vero. Sembra che Microsoft abbia finalmente fatto qualcosa al riguardo, migliaia di chiamate di supporto devono aver ispirato. Non sono sicuro di quando sia successo, da qualche parte intorno a 4.5 o 4.6, sospetto. Ora sono mantenuti in vita mentre ticchettano, [TimerQueue.s_queue] (http://referencesource.microsoft.com/#mscorlib/system/threading/timer.cs,75523a07eb2de983) si prende cura di esso. –
Grazie, ma allora il timer dovrebbe essere tenuto in vita in entrambi gli scenari? Perché sopravvive solo al secondo? Sto usando .NET 4.6.1. –
Mi sembra un insetto. Solo il metodo Change() ottiene il timer aggiunto alla coda del timer, il costruttore si dimentica di farlo. È piuttosto difficile immaginare che ciò sia stato intenzionale, prendi in considerazione di segnalarlo. –