I am trying to understand why a Windows.Forms.Timer
is not disposed when the form
that created it is. I have this simple form:
public partial class Form1 : Form {
private System.Windows.Forms.Timer timer;
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
timer = new Timer();
timer.Interval = 1000;
timer.Tick += new EventHandler(OnTimer);
timer.Enabled = true;
}
private void OnTimer(Object source, EventArgs e) {
Debug.WriteLine("OnTimer entered");
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e) {
this.Dispose();
}
}
When I close it, this.Dispose
is called but the timer firing event continues to be called. I thought that the Dispose
was freeing all objects owned by the disposed object. Is that untrue? Does Timer
have a specific behavior?
For now, I found that the way to dispose of the timer is to do timer.Tick -= OnTimer;
- I call it then in the Form1_FormClosed
event. Is it the good solution or should I do otherwise?
Or is it simply better to do:
private void Form1_FormClosed(object sender, FormClosedEventArgs e) {
timer.Dispose();
this.Dispose();
}
?
As I told you in my previous comment you should try:
private Form1_FormClosing(...)
{
timer.Stop();
timer.Tick -= new EventHandler(OnTimer);
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
timer.Dispose();
timer = null;
}
This is good because you prevent timer to cycle again (in FormClosing) and you can check in other parts (non in this example because you're closing the form, but as example) if that object (timer) has been deleted before using it.
So in other parts you can do
if (timer != null) // Note: this is false if you just use timer.Dispose()
{
....
}
The only proper way to dispose disposable members of an IDisposable
class is to do it inside its Dispose(bool disposing)
method (check the MSDN article). In other words, you can open the autogenerated Form.Designer.cs
file and put it inside the proper method.
On the other hand, if you add the Timer
through VS Designer (instead of instantiating it yourself), it will get added to the components
container:
// autogenerated inside Form.Designer.cs, InitializeComponent() method
this.timer = new System.Windows.Forms.Timer(this.components);
and then properly disposed when components
member is disposed:
// autogenerated inside Form.Designer.cs, Dispose(bool disposing) method
if (disposing && (components != null))
{
components.Dispose();
}
If you want to do this yourself, keep in mind that designer does not instantiate components
if it doesn't think it's needed. So, components
might be null
in your case.
The simplest way to solve this: add the timer by dragging it from the toolbox, then start it inside the Form_Load
handler.
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