从不同的表单关闭WinForm应用程序

时间:2013-02-12 17:47:37

标签: c# winforms

这似乎是一个愚蠢的问题,但我只是想确保我做对了。我的主要形式大部分时间都不可见。要打开它,我有一个NotifyIcon。其中一个菜单选项是Exit Application。我还有一些静态全局变量需要在应用程序关闭之前处理掉。所以在program.cs我有这个。

    [STAThread]
    static void Main()
    {
        InitializeApplication();
        InitializeMainForm();
        Application.Run(main);
    }
    private static void InitializeApplication()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.ApplicationExit += Application_ApplicationExit;
    }
    private static void InitializeMainForm()
    {
        main = new AssignButtonForm();
        main.FormClosing += main_FormClosing;
        Globals.StartNotify();
    }

    static void main_FormClosing(object sender, FormClosingEventArgs e)
    {
        var dlg = MessageBox.Show("Turn off Application?", "Exit?", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
        if (dlg == DialogResult.OK)
        {
            Globals.notifyIcon1.Dispose();
            Application.Exit();
        }
        else
        {
            e.Cancel = true;
        }
    }

所以我希望这是调用它的正确方法。

    private void exitToolStripMenuItem_Click(object sender, EventArgs e)
    {
        this.Hide();
        Application.OpenForms[0].Close();
    }

是正确的吗?还是有更好的方法?

修改

好吧所以我的一个类有自己的Dispose方法

public class KeymonNotifyIcon : IDisposable
{
    public KeymonNotifyIcon()
    {
        InitializeComponent();
        keymonMenuStrip.SetupKeysSelected += OnSetupKeysSelected;
    }
    ~KeymonNotifyIcon()
    {
        Dispose();
    }
    public void Dispose()
    {
        if (notifyIcon1 != null)
            notifyIcon1.Dispose();

        if (keymonMenuStrip != null)
            keymonMenuStrip.Dispose();
    }
}

全球类

public static class Globals
{
    public static TraceSource trace = new TraceSource("Keymon");
    public static KeymonNotifyIcon notifyIcon1;
    public static void StartNotify()
    {
        notifyIcon1 = new KeymonNotifyIcon();
    }
}

2 个答案:

答案 0 :(得分:2)

实际上,我相当确定Application.Exit将为您调用所有Dispose方法(只要您已实施IDisposable

请参阅this question,其中引用了this question

答案 1 :(得分:1)

如果您的程序刚关闭,那些未被垃圾回收的对象将运行终结器recommended pattern实现IDisposable的对象具有终结器以确保IDisposable运行。据我所知,.NET BCL类始终遵循该模式。但是,您自己的或第三方/开源组件可能不遵循该模式。

注意:MSDN上的链接模式不会调用GC.SuppressFinalize。查看how to use it以减少GC开销。

单独实施IDisposable不足以确保对象得到妥善处理。

如果您有静态引用的实现IDisposable的对象,那么从应用程序关闭事件中明确调用它们IDisposable.Dispose()是一个更可靠的解决方案。

修改

您的Dispose实现将导致Dispose()在拥有的对象上被调用两次,因为:

if (notifyIcon1 != null)
        notifyIcon1.Dispose();

未将notifyIcon1设置为null,终结器会再次无条件地调用Dispose()

此外,您将始终导致终结器运行(这使得该类的GC更加昂贵),因为您未在Dispose()中调用GC.SuppressFinalize()