Zgodnie z MSDN należy zachować odniesienie do System.Threading.Timer, w przeciwnym razie zostanie pobrane śmieci. Więc jeśli ten kod, to nie pisać żadnych wiadomości (co jest oczekiwane zachowanie):C# Timery i usuwanie śmieci
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);
}
Jeśli jednak zmodyfikować kod nieznacznie przechowując timer w tymczasowej zmiennej lokalnej, to przetrwa i zapisuje komunikat:
public static void RunTimer()
{
var timer = new Timer(s => Console.WriteLine("Hello"));
timer.Change(TimeSpan.FromSeconds(1), TimeSpan.Zero);
}
Podczas usuwania śmieci najwyraźniej nie ma sposobu uzyskania dostępu do licznika z katalogu głównego lub obiektów statycznych. Czy możesz wyjaśnić, dlaczego czasomierz przetrwał? Gdzie jest zachowane odniesienie?
To z pewnością * używane *, aby było prawdziwe. Wygląda na to, że Microsoft w końcu coś z tym zrobił, tysiące zgłoszeń do wsparcia musiało być inspirujących. Nie jestem pewien, kiedy to się stało, gdzieś około 4,5 lub 4,6, podejrzewam. Są teraz utrzymywane przy życiu, gdy tykają, [TimerQueue.s_queue] (http://referencesource.microsoft.com/#mscorlib/system/threading/timer.cs,75523a07eb2de983) zajmuje się tym. –
Dzięki, ale czy w obu scenariuszach powinien być utrzymany zegar? Dlaczego przetrwa tylko drugi? Używam .NET 4.6.1. –
To wygląda mi na błąd. Tylko metoda Change() pobiera licznik dodany do kolejki timera, konstruktor zapomina o tym. Trudno sobie wyobrazić, że było to celowe, rozważ zgłoszenie. –