-3

I currently have 3 forms, a main menu, form 2 and form 3. Is there an optimised way of opening forms (and closing them) as when I switch between them they are taking memory up and I can quickly get to a few GBs usage switching between them over a few minutes.

   private void button2_Click(object sender, EventArgs e)
        {
            this.Hide();
            NewForm NewForm = new NewForm();
            
            NewForm.ShowDialog();
            this.Close();
            this.Dispose();

I've found if comment out this.Hide() my forms aren't actually closing. How can I close the forms when the new one is opened?

Zed1129
  • 21
  • 5
  • It looks like you're creating a new form on every click. Try creating just one instance and dynamically hiding/showing it instead. – Cameron Sep 21 '20 at 16:02
  • 1
    `NewForm.ShowDialog();` blocks what comes after it because it's modal, so it won't run that code until after NewForm is closed. – LarsTech Sep 21 '20 at 16:06
  • _a few GBs_ : What a few GD today? Are you sure there actaully is a problem?? Most likely the GC sees no reason to do anything; neither should you.. – TaW Sep 21 '20 at 16:06
  • https://stackoverflow.com/a/10769349/17034 – Hans Passant Sep 21 '20 at 17:06

1 Answers1

2

Presumably, you're using ShowDialog() to keep the app from exiting when the original, main form is closed?

A different approach would be to use the overload of Application.Run that receives an ApplicationContext.

Then you could write your own "application context" and tell the application to only exit when there are no more forms open. This will allow you to switch from ShowDialog() to Show(). The small change means the old form will be disposed of since code execution continues after Show().

Back in our ApplicationContext class, we can wire up the Idle event and check the count of open forms in Application.OpenForms, letting us know when all forms have been closed and it is time to shut down the application.

So your "program.cs", would change to:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new MyAppContext(new Form1()));
    }
}

public class MyAppContext : ApplicationContext
{
    public MyAppContext(Form startingForm)
    {
        startingForm.Show();
        Application.Idle += Application_Idle;
    }

    private void Application_Idle(object sender, EventArgs e)
    {
        if (Application.OpenForms.Count == 0)
        {
            Application.Exit();
        }
    }

}

Now, whenever you want to switch forms, just make sure to Show() the new form before you Dispose() of the current one:

private void button1_Click(object sender, EventArgs e)
{
    Form2 f2 = new Form2();
    f2.Show(); // make sure you "Show()" the new form BEFORE disposing of the current one below
    this.Dispose(); // dispose of the current form
}

With all that in place, the application will shut down automatically once the last form is closed, and the old forms should get disposed of properly.

Remember, though, that the GC manages memory for you...and it might decide that it is going to hold on to that memory to make things load faster in the future. This approach simply addresses the problem that the Dispose() call wasn't being hit since ShowDialog() was stopping execution.

Idle_Mind
  • 38,363
  • 3
  • 29
  • 40