I want something very simple
// increment counter
Interlocked.Increment(ref _counter);
// automatically decrement counter after 1 sec
Timer timer = new Timer((o) => {
Interlocked.Decrement(ref _counter);
(o as Timer).Dispose();
}, timer, 1000, Timeout.Infinite);
this code, however, is not compile-able
Use of unassigned local variable 'timer'
Any easy way to fix that? It must be Threading.Timer
.
P.S.: I am not sure if I must call Dispose
, it's obviously un-managed resource and it's IDisposable
, still on msdn they warn
As long as you are using a Timer, you must keep a reference to it. As with any managed object, a Timer is subject to garbage collection when there are no references to it. The fact that a Timer is still active does not prevent it from being collected.
And I actually want it to be be collected (auto-disposed?). So, to dispose or to not dispose?
Best practices when working in C# say that you should clean up your resources if the class implements IDisposable interface. There are two ways to dispose the Timer: Dispose the timer by calling the Dispose() method inside a try/catch block to avoid exception.
Timer is not thread-safe.
To end or quit the timer, one must use a cancel() function. Importing the threading class is necessary for one to use the threading class. The calling thread can be suspended for seconds using the function time. sleep(secs).
The application thread creates the timer, which waits one second and then executes the CheckStatus callback method every 250 milliseconds. The application thread then blocks until the AutoResetEvent object is signaled. When the CheckStatus callback method executes maxCount times, it calls the AutoResetEvent.
There's a pattern for that:
Timer timer = null;
timer = new Timer...
Now you can use timer
in the lambda body. This is basically a way to make the compiler happy while doing the same thing.
Be sure to dispose of that timer. Timers might be backed up by an OS handle resource (the CLR implementation changed a few times I believe). A timer also contains a GC handle I believe. This is harmless not to dispose of most of the time. But who knows what rare resource exhaustion you can provoke with a high volume of undisposed timers.
Doing a little code review: If you expect a cast to always work, do not use as
because as
documents that failure is an expected case. Not: (o as Timer)
. Instead: ((Timer)o)
.
Self disposing won't work if you don't keep a reference to it. You risk having it garbage collected, even if it's not periodical. So, it may be garbage collected before even it ticks the first time.
From the System.Threading.Timer documentation:
As long as you are using a Timer, you must keep a reference to it. As with any managed object, a Timer is subject to garbage collection when there are no references to it. The fact that a Timer is still active does not prevent it from being collected.
On the other hand, it will be released via it's finalizer even if you don't dispose it (although not a good practice to rely on this). This can be seen in the Timer's source, on ReferenceSource.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With