Timer not disposed when form is

12,045

Solution 1

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()
{
    ....
}

Solution 2

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.

Solution 3

 private void Form1_FormClosed(object sender, FormClosedEventArgs e) 
 {        timer.Stop();    } 

I shouldn't put the this.Dispose(); in form closing event just stop timer.

Solution 4

The EventHandler is the persisting reference, remove the reference and Stop the timer on the Closing Event or as soon as its not required. If you want to check the Timer is disposed check it in the Closed Event

Solution 5

The simple Timer.Dispose() deletes timer resources, including stoping the timer from firing in the future.

However, it is possible that after Dispose() returns, there are callbacks that are either actively executing or sitting in the thread pool's work queue waiting to execute.

The second overload, Timer.Dispose(WaitHandle) will signal the passed in object once all callbacks for the timer have completed. This can be any WaitHandle, for instance a ManualResetEvent.

To simplify things, you can pass in WaitHandle.InvalidHandle and Timer.Dispose() will return only when all callbacks have completed. This avoids having to allocate a true event object and is usually what you want to do.

Since WaitHandle is abstract, you need to use a little hack, which is to create your own subclass.

class InvalidWaitHandle : WaitHandle {}
Timer tmr = new Timer(...);
tmr.Dispose(new InvalidWaitHandle);
Share:
12,045

Related videos on Youtube

Otiel
Author by

Otiel

Profile picture credits: http://codegolf.stackexchange.com/a/22326/14595

Updated on June 04, 2022

Comments

  • Otiel
    Otiel almost 2 years

    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?

    EDIT

    Or is it simply better to do:

    private void Form1_FormClosed(object sender, FormClosedEventArgs e) {
        timer.Dispose();
        this.Dispose();
    }
    

    ?

    • Oskar Kjellin
      Oskar Kjellin over 12 years
      The disposing should be done in the IDisposable method Dispose, not in FormClosing
    • Marco
      Marco over 12 years
      in FormClosing event you should stop timer timer.Enabled = false; and then timer.Dispose(); timer = null;
    • user1703401
      user1703401 over 12 years
      Drop a timer from the toolbox onto the form with the designer. Now it is all automatic.