What happens to dead timers?

J

Jonathan Payne

I seem to be leaking a timer when I close a form but can't work out
why.

I have a very simple form ("TestForm" in the example below) that
contains a timer and a button that closes the form by calling Close. I
display the form by calling ShowDialog on it and then call Dispose when
ShowDialog returns. If I set a break point in the timer event, I can
see the timer being called when I show the form. If I then close the
form, the timer continues to be called, even after I have called
dispose.

I do not understand how this is possible. I would have thought that
calling Dispose on the form would have disposed all the controls in
including the timer and hence stopped the timer from firing. Also, if
the form has been disposed, what object is the timer calling?

I could disable the timer in the OnClosing event but I would like to
work out why this is happening in the first place so I do not end up
just hiding the symptoms.

Do I need to do extra work to dispose of a timer?

Attached is a small sample application that demonstrates this problem.
I tried to cut the code down as much as possible but it still a bit
long (sorry). To test, run the code and press the test button on the
first dialog. Add a break point in the timer event and see that it is
triggered. Next close the form. At this point the timer still seems
to be triggered.

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.ComponentModel;

namespace DeviceApplication1
{
static class Program
{
class TestForm : Form
{
public TestForm()
{
this.button1 = new System.Windows.Forms.Button();
this.timer1 = new System.Windows.Forms.Timer();
this.SuspendLayout();
this.button1.Location = new System.Drawing.Point(48, 148);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(72, 20);
this.button1.TabIndex = 1;
this.button1.Text = "Close";
this.button1.Click += new
System.EventHandler(this.button1_Click);
this.timer1.Enabled = true;
this.timer1.Interval = 500;
this.timer1.Tick += new
System.EventHandler(this.timer1_Tick);
this.AutoScaleDimensions = new System.Drawing.SizeF(96F,
96F);
this.AutoScaleMode =
System.Windows.Forms.AutoScaleMode.Dpi;
this.AutoScroll = true;
this.ClientSize = new System.Drawing.Size(240, 294);
this.Controls.Add(this.button1);
this.Name = "TestForm";
this.Text = "TestForm";
this.ResumeLayout(false);
}

private void button1_Click(object sender, EventArgs e)
{
Close();
}

private void timer1_Tick(object sender, EventArgs e)
{

}
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Timer timer1;
}

public partial class Form1 : Form
{
public Form1()
{
this.btnTest = new System.Windows.Forms.Button();
this.SuspendLayout();
this.btnTest.Location = new System.Drawing.Point(114, 83);
this.btnTest.Name = "btnTest";
this.btnTest.Size = new System.Drawing.Size(72, 20);
this.btnTest.TabIndex = 0;
this.btnTest.Text = "Test";
this.btnTest.Click += new
System.EventHandler(this.btnTest_Click);
this.AutoScaleDimensions = new System.Drawing.SizeF(96F,
96F);
this.AutoScaleMode =
System.Windows.Forms.AutoScaleMode.Dpi;
this.AutoScroll = true;
this.ClientSize = new System.Drawing.Size(240, 294);
this.Controls.Add(this.btnTest);
this.Name = "Form1";
this.Text = "Form1";
this.MinimizeBox = false;
this.ResumeLayout(false);
}

private void btnTest_Click(object sender, EventArgs e)
{
TestForm t = new TestForm();
t.ShowDialog();
t.Dispose();
}

private void button1_Click(object sender, EventArgs e)
{
Close();
}

private System.Windows.Forms.Button btnTest;
private System.Windows.Forms.Button button1;
}

[MTAThread]
static void Main()
{
Application.Run(new Form1());
}
}
}


Jonathan
 
G

Guest

Yes you're right the From.Dispose doesn't dispose controls automatically.
Take a look at this thread:

http://groups.google.com/group/micr...ompactframework&rnum=3&hl=en#e71195aad20bc8b5

--
Alex Yakhnin, .NET CF MVP
www.intelliprog.com | www.opennetcf.org


Jonathan Payne said:
I seem to be leaking a timer when I close a form but can't work out
why.

I have a very simple form ("TestForm" in the example below) that
contains a timer and a button that closes the form by calling Close. I
display the form by calling ShowDialog on it and then call Dispose when
ShowDialog returns. If I set a break point in the timer event, I can
see the timer being called when I show the form. If I then close the
form, the timer continues to be called, even after I have called
dispose.

I do not understand how this is possible. I would have thought that
calling Dispose on the form would have disposed all the controls in
including the timer and hence stopped the timer from firing. Also, if
the form has been disposed, what object is the timer calling?

I could disable the timer in the OnClosing event but I would like to
work out why this is happening in the first place so I do not end up
just hiding the symptoms.

Do I need to do extra work to dispose of a timer?

Attached is a small sample application that demonstrates this problem.
I tried to cut the code down as much as possible but it still a bit
long (sorry). To test, run the code and press the test button on the
first dialog. Add a break point in the timer event and see that it is
triggered. Next close the form. At this point the timer still seems
to be triggered.

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.ComponentModel;

namespace DeviceApplication1
{
static class Program
{
class TestForm : Form
{
public TestForm()
{
this.button1 = new System.Windows.Forms.Button();
this.timer1 = new System.Windows.Forms.Timer();
this.SuspendLayout();
this.button1.Location = new System.Drawing.Point(48, 148);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(72, 20);
this.button1.TabIndex = 1;
this.button1.Text = "Close";
this.button1.Click += new
System.EventHandler(this.button1_Click);
this.timer1.Enabled = true;
this.timer1.Interval = 500;
this.timer1.Tick += new
System.EventHandler(this.timer1_Tick);
this.AutoScaleDimensions = new System.Drawing.SizeF(96F,
96F);
this.AutoScaleMode =
System.Windows.Forms.AutoScaleMode.Dpi;
this.AutoScroll = true;
this.ClientSize = new System.Drawing.Size(240, 294);
this.Controls.Add(this.button1);
this.Name = "TestForm";
this.Text = "TestForm";
this.ResumeLayout(false);
}

private void button1_Click(object sender, EventArgs e)
{
Close();
}

private void timer1_Tick(object sender, EventArgs e)
{

}
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Timer timer1;
}

public partial class Form1 : Form
{
public Form1()
{
this.btnTest = new System.Windows.Forms.Button();
this.SuspendLayout();
this.btnTest.Location = new System.Drawing.Point(114, 83);
this.btnTest.Name = "btnTest";
this.btnTest.Size = new System.Drawing.Size(72, 20);
this.btnTest.TabIndex = 0;
this.btnTest.Text = "Test";
this.btnTest.Click += new
System.EventHandler(this.btnTest_Click);
this.AutoScaleDimensions = new System.Drawing.SizeF(96F,
96F);
this.AutoScaleMode =
System.Windows.Forms.AutoScaleMode.Dpi;
this.AutoScroll = true;
this.ClientSize = new System.Drawing.Size(240, 294);
this.Controls.Add(this.btnTest);
this.Name = "Form1";
this.Text = "Form1";
this.MinimizeBox = false;
this.ResumeLayout(false);
}

private void btnTest_Click(object sender, EventArgs e)
{
TestForm t = new TestForm();
t.ShowDialog();
t.Dispose();
}

private void button1_Click(object sender, EventArgs e)
{
Close();
}

private System.Windows.Forms.Button btnTest;
private System.Windows.Forms.Button button1;
}

[MTAThread]
static void Main()
{
Application.Run(new Form1());
}
}
}


Jonathan
 
J

Jonathan Payne

Thanks - the link you provided and your previous posts were exeactly
what I need to know.

This behaviour does seem a bit strange as it makes it very easy to hold
on to expensive resources like timers far longer than is necassary.

Jonathan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top