8

我们有一个包含数千个表单的 Windows 窗体应用程序。

其中许多通过 ShowDialog() 方法临时显示为对话框。

这个应用程序已经存在多年,我们发现由于表单或它使用的控件中的各种资源泄漏,许多表单没有及时收集垃圾。

具体来说,我们发现了 GDI+ 资源没有被正确处理的例子,尽管可能还有其他类型的资源泄漏尚未被描述。

虽然解决这个问题的正确方法显然是遍历每一个表单和每一个控件,并消除所有的资源问题。这需要一些时间来完成。

作为短期替代方案,我们发现在表单上显式调用 Dispose() 似乎会启动垃圾收集过程,并且会立即释放表单及其资源。

我的问题是,将每个表单的 ShowDialog() 块包装在 using 语句中,以便在显示表单后调用 Dispose() 是否是一种合理的解决方法,这也是一个普遍的好习惯吗?

例如,从这里更改现有代码:

public void ShowMyForm()
{
    MyForm myForm = new MyForm();
    myForm.ShowDialog();
}

对此:

public void ShowMyForm()
{
    using (MyForm myForm = new MyForm())
    {
        myForm.ShowDialog();
    }
}

在我们的测试中,MyForm 的 Dispose() 方法永远不会为第一个示例调用,但它会立即为第二个示例调用。

当我们花时间跟踪每个特定的资源问题时,这似乎是一种合理的短期解决方法吗?

是否有其他我们可以考虑的短期解决方法和/或用于识别和解决这些类型的资源问题的方法?

4

3 回答 3

14

根据MSDN,您必须在使用 ShowDialog 显示的表单上显式调用 Dispose(与 Show 方法不同):

当窗体显示为模式对话框时,单击关闭按钮(窗体右上角带有 X 的按钮)会导致窗体隐藏并且 DialogResult 属性设置为 DialogResult.Cancel。与非模式表单不同,当用户单击对话框的关闭表单按钮或设置 DialogResult 属性的值时,.NET Framework 不会调用 Close 方法。相反,该表单被隐藏并且可以再次显示而无需创建对话框的新实例。因为显示为对话框的窗体是隐藏的而不是关闭的,所以当您的应用程序不再需要该窗体时,您必须调用该窗体的 Dispose 方法。

于 2011-11-29T17:39:11.063 回答
2

对于模式对话框,您应该使用以下模式:

using ( var dlg = new MyDialog() )
{
    // other code here to initialize, etc.
    dlg.ShowDialog();
}

由于MyDialog是从Form派生的,并且 Form 实现了IDisposable,因此此模式将正确清理您的对话框。

这不应该是“短期解决方法”,而是您应该调用所有模式对话框的标准方式。

无模式对话是另一回事。您需要自己跟踪它们,并在应用程序的适当位置调用Dispose 。

于 2011-11-29T17:44:52.273 回答
1

通常,将using语句用于实现 IDisposable 的对象是一种好方法。

小样情况:

假设您有第三方“组件”。您无法知道内部发生了什么,也许这个对象会创建一个临时文件并删除Dispose. 如果您不打电话也不Dispose()使用using该文件将永远不会被删除。

在您的情况下,只要您打开表单,您也可以这样做modal

于 2011-11-29T17:37:01.750 回答