C # Timers and Garbage Collection

According to MSDN, the reference to System.Threading.Timer must be stored otherwise, it will receive garbage collection. Therefore, if I run this code, it does not write any message (which is the expected behavior):

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); } 

However, if I modify the code a little while keeping the timer in a temporary local variable, it will survive and write a message:

 public static void RunTimer() { var timer = new Timer(s => Console.WriteLine("Hello")); timer.Change(TimeSpan.FromSeconds(1), TimeSpan.Zero); } 

During garbage collection, there seems to be no way to access the timer from root or static objects. So can you explain why the timer survives? Where is this link saved?

+8
garbage-collection c # timer
source share
1 answer

Each Timer refers to a TimerHolder , which refers to a TimerQueueTimer . The implementation maintains an internal reference to TimerQueueTimer by calling UpdateTimer() .

Under normal circumstances, your timer can be compiled, terminating the TimerHolder and removing the TimerQueueTimer from the internal queue. But a simple Timer(TimerCallback) constructor Timer(TimerCallback) calls TimerSetup() with Timer itself as a state. Therefore, in this particular case, the state of TimerQueueTimer refers to Timer , preventing its collection.

The effect is not related to saving a temporary local variable. It so happened that this works because of the internal elements of the Timer mechanism. It is much clearer and safer to store a link to your timer, as recommended by MSDN.

+3
source share

All Articles