【问题标题】:Close WinForm Application from different Form从不同的表单关闭 WinForm 应用程序
【发布时间】:2013-02-12 17:47:36
【问题描述】:

这似乎是一个愚蠢的问题,但我只是想确保我做对了。我的主要形式大部分时间都不可见。要打开它,我有一个 NotifyIcon。菜单选项之一是退出应用程序。我还有一些静态全局变量需要在应用程序关闭之前处理掉。所以在 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();
    }
}

【问题讨论】:

    标签: c# winforms


    【解决方案1】:

    实际上,我相当肯定Application.Exit 会为你调用你所有的Dispose 方法(只要你已经实现了IDisposable

    参见this question,它引用了this question

    【讨论】:

    • 全部???甚至那些不属于全局静态类中的主要形式的部分? (一分钟后查看编辑后的帖子)
    • 如果你实现了IDisposable
    • 如果您想确保处理所有内容,您可以在OnFormClosing-Event 中放置一个 Dispose-Method。但这不应该是必要的!
    • 只有当 IDisposable 对象也有一个终结器调用 IDisposable.Dispose() 时才成立。
    【解决方案2】:

    如果您的程序刚刚关闭,尚未进行垃圾回收的对象将运行其终结器。实现IDisposable 的对象是recommended pattern 有一个终结器以确保运行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()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-08
      • 2014-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-12
      • 2011-03-27
      相关资源
      最近更新 更多