If I have an active System.Threading.Timer and I set it to null, is it stopped?
I realize that it is more proper to call .Dispose() but I would like an
I know you're asking about the System.Threading.Timer class, but I want to point out something rather important.
The answers provided so far are good. Logan and SLaks are right that setting any variable to null has no direct effect on the object to which the variable was previously assigned. Russell is right that when the garbage collector does eventually dispose of the timer, however, it will stop.
SLaks indicated that after setting a timer reference to null, there may be lingering references. In the simple example of one System.Threading.Timer reference, this is not the case.
But, if you have, for example, a System.Timers.Timer, and you handle its Elapsed event, then setting it to null will leave a reference and the timer will continue to run forever.
So consider this code for example:
var t = new System.Timers.Timer(1000.0);
t.AutoReset = true;
t.Elapsed += (sender, e) => Console.WriteLine(DateTime.Now);
Console.Write("Press Enter to start the timer.");
Console.ReadLine();
t.Start();
Console.Write("Press Enter to set t to null.");
Console.ReadLine();
// This will not stop the timer. It actually does nothing at all to the timer
// to which t has been assigned.
t = null;
Console.Write("Press Enter again to perform a garbage collection.");
Console.ReadLine();
// This STILL will not stop the timer, as t was not the only reference to it
// (we created a new one when we added a handler to the Elapsed event).
GC.Collect();
Console.Write("t is null and garbage has been collected. Press Enter to quit.");
Console.ReadLine();
In the example above, as there is code holding onto a reference to t in order to handle its Elapsed event, the timer will never stop.
Again, I realize this is not the class you asked about; I only bring this up to point out that it is not always obvious whether in fact you do or do not have any more references to a given object.
UPDATE: It seems some confusion has sprung up on the topic of whether the statement I made above is equally true of a System.Threading.Timer object; it is not. To verify this, consider the following modification of the above code:
Console.Write("Press Enter to start the timer.");
Console.ReadLine();
var t = new System.Threading.Timer(
state => { Console.WriteLine(DateTime.Now); },
null,
0,
1000
);
Console.Write("Press Enter to set t to null.");
Console.ReadLine();
// This will not stop the timer. It actually does nothing at all to the timer
// to which t has been assigned. HOWEVER, if/when the GC comes around to collect
// garbage, it will see that said timer has no active references; and so it will
// collect (and therefore finalize) it.
t = null;
Console.Write("Press Enter again to perform a garbage collection.");
Console.ReadLine();
// This WILL cause the timer to stop, as there is code in the type's
// finalizer to stop it.
GC.Collect();
Console.Write("t is null and garbage has been collected. Press Enter to quit.");
Console.ReadLine();
Here's why it doesn't work for System.Timers.Timer (or any type that has events, actually):
The answer is very easy to miss when we've defined our event handler like this:
t.Elapsed += (sender, e) => Console.WriteLine(DateTime.Now);
What if I defined my handler like this instead?
t.Elapsed += (sender, e) => Console.WriteLine(sender.GetType());
Oh right! That sender argument that nobody ever pays any attention to!
The event-handling infrastructure provided by .NET requires that objects handling events maintain references to objects raising events. Otherwise, the contract provided by the very signature of the EventHandler delegate and all its cousins would be violated.
The moral of this story is: as soon as you add a handler to an event, you have created a new reference to an object. The only way to allow that object to be garbage collected after this point is to remove the handler -- but this may be quite difficult if you've set the only other reference to said object to null (this is one of the very few examples of a case where a .NET program may have a "memory leak").