Dispose form after closing

Mironline picture Mironline · Aug 31, 2010 · Viewed 32.4k times · Source

I have got the new problem with opening and closing form in C#.

My problem is how to dispose the form after closing .

here is my code :

Program.cs:

static class Program
{
    public static Timer timer;

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        timer = new Timer { Interval = 1000};
        timer.Start();

        Application.Run(new Form1());
    }
}

Form1.cs:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Form2 form = new Form2();
        form.ShowDialog();
       /// I've tried Dispose() method . but didn't work
    }
}

Form2.cs:

public partial class Form2 : Form
{
    public Form2()
    {
        InitializeComponent();
    }

    private void Form2_Load(object sender, EventArgs e)
    {
        Program.timer.Tick += timer_Tick;    
        Close();
        // I've tried Dispose() method instead of Close() but didn't work
    }

    private int count = 0; 
    void timer_Tick(object sender, EventArgs e)
    {
        count++;
        if (count == 5) MessageBox.Show("");
    }
}

Edited : My question is : why the message box shows after 5 seconds when the form2 has closed!

Answer

Henk Holterman picture Henk Holterman · Aug 31, 2010

Edit: This question turns out to be about Dispose.

Firstly, Dispose has noting to do with garbage collection. The following happens:

  1. You have a global Timer instance
  2. You create form2
  3. Form2 subscribes to the timer
  4. Form2 is Closed and/or Disposed
  5. The Timer event fires, increments the counter and shows a MessageBox
  6. The Timer event keeps firing until the App closes.

The main point to understand is that Close/Dispose only change the status of the Form, they don't (can't) 'delete' the instance. So the (closed) form is there, the counter field is still there and the Event fires.


OK, part 1:

A using () {} block would be better but this should work:

    private void button1_Click(object sender, EventArgs e)
    {
        Form2 form = new Form2();
        form.ShowDialog();
       /// I've tried Dispose() method . but didn't work
        form.Dispose(); // should work
    }

If not, please describe "doesn't work".


    private void Form2_Load(object sender, EventArgs e)
    {
        Program.timer.Tick += timer_Tick;    
        Close();
       /// I've tried Dispose() method instead of Close() . but didn't work
    }

This is strange, but I'll assume that it is artifical code for the question.

Your global Program.Timer now stores a reference to your Form2 instance and will keep it from being collected. It does not prevent it from being Disposed/Close so your timer will keep firing for a Closed Form, and that will usually fail and cause other problems.

  1. Don't do this (give Form2 it's own timer)
  2. Use a FormClosed event to unsubscribe: Program.timer.Tick -= timer_Tick;