简体   繁体   中英

How to properly dispose multiple forms

Question : How to properly dispose the ScreenSaverForm(s) that is created in the method ShowScreensaver ?

When I run CODE ANALYSIS from Visual Studio it reports the following: In method 'Program.ShowScreenSaver()', call System.IDisposable.Dispose on object 'ssf' before all references to it are out of scope .

I don't understand how to do that because the Application enters an anonymous message loop afters exiting method ShowScreenSaver() . Only the screensavers themselves can stop the application by calling Application.Exit() on mousemove-event. Should the screensaverForms dispose themselves perhaps?

static class Program
{
    [STAThread]
    static void Main(string[] args)
    {
                ShowScreenSaver();
                Application.Run();
    }

    /// <summary>
    /// Display the form on each of the computer's monitors.
    /// </summary>
    static void ShowScreenSaver()
    {
        ScreenSaverForm ssf;
        foreach (Screen screen in Screen.AllScreens)
        {
            ssf = new ScreenSaverForm(screen.Bounds);
            ssf.Show();
        }
    }
}

Simplified code of the Screensaver class

public partial class ScreenSaverForm : Form
{
    public ScreenSaverForm()
    {
        InitializeComponent();

        //Display pretty image
        ShowprettyImage();
    }
    private void ScreenSaverForm_MouseMove(object sender, MouseEventArgs e)
    {
        if (!mouseLocation.IsEmpty)
         {
             // Terminate if mouse is moved a significant distance
             if (Math.Abs(mouseLocation.X - e.X) > 25 ||
                 Math.Abs(mouseLocation.Y - e.Y) > 25)
                 Application.Exit();
         }

         // Update current mouse location
         mouseLocation = e.Location;
    }
}

To comply with code analysis, you can just do:

static void ShowScreenSaver() {
    foreach (Screen screen in Screen.AllScreens) {
        ScreenSaverForm form = new ScreenSaverForm(screen.Bounds);

        form.FormClosed += (sender, e) => {
            form.Dispose();
        };

        form.Show();
    }
}

If you know when you will be done with it and you no longer need it, get rid of it.

Let them dispose themselves. They'll be freed up when the screensaver stops and the executable is shut down.

If you really want to, you can make the ssf object a class level field and dispose of it when the application shuts down, and that would be the best practice.

You could also have ShowScreenSaver return the form, and use the Application.Run that takes a form as a parameter, and add an event to the application exit that will dispose of it for you.

ScreenSaverForm form = ShowScreenSaver();
Application.ApplicationExit += (sender, e) => form.Dispose();
Application.Run(form);

First I would say bring ssf variable into the loop

static void ShowScreenSaver()
{

    foreach (Screen screen in Screen.AllScreens)
    {
        ScreenSaverForm ssf = new ScreenSaverForm(screen.Bounds);
        ssf.Show();
    }
}

This may already resolve a problem.

It's enough to manage, if you need that , the disposal inside the form itself.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM