按钮单击导致子窗体不被释放C#

按钮单击导致子窗体不被释放C#,c#,.net,garbage-collection,C#,.net,Garbage Collection,我有一个子表单,其中包含一个RichTextBox,该表单加载了RichText的资源文件 单击关闭子窗体的按钮时(使用close()),窗体将关闭并返回到父窗体。然而,这些资源并未得到处置。事实上,在我的鼠标几乎用完之后,我的记忆真的升级了 为了测试资源是否最终会被释放,我在父窗体上设置了一个窗体计时器来加载子窗体,并在子窗体中设置了另一个计时器来调用Close()。这一次,资源在大约5或6个打开/关闭周期后释放 嗯。。我想。所以我改变了设置来模拟现实。这次我将子窗体计时器触发事件更改为包含b

我有一个子表单,其中包含一个
RichTextBox
,该表单加载了RichText的资源文件

单击关闭子窗体的按钮时(使用
close()
),窗体将关闭并返回到父窗体。然而,这些资源并未得到处置。事实上,在我的鼠标几乎用完之后,我的记忆真的升级了

为了测试资源是否最终会被释放,我在父窗体上设置了一个窗体计时器来加载子窗体,并在子窗体中设置了另一个计时器来调用
Close()
。这一次,资源在大约5或6个打开/关闭周期后释放

嗯。。我想。所以我改变了设置来模拟现实。这次我将子窗体计时器触发事件更改为包含
button1.PerformClick()
,它触发
button1
pressed事件,其中包含
Close()
语句。这一次,在我中止测试之前,资源没有释放,内存使用量上升到1GB

为什么包含
Close()
的按钮事件与包含
Close()
的计时器事件不同

好的。。以下是父窗体上用于打开子窗体的代码:-

private void showSplashScreen()
{
    // Instantiating SplashScreen
    SplashScreen splash = new SplashScreen();
    // Displaying SplashScreen
    splash.ShowDialog();
}
下面是子表单上用于关闭表单的代码:-

private void button1_Click( object sender, EventArgs e )
{
    Close();
}


private void timer1_Tick( object sender, EventArgs e )
{
    button1.PerformClick();
//    Close();
}

以这种方式运行时,内存使用率会上升。。但是如果
button1.PerformClick()
被注释掉,并且
Close()
未注释的资源被定期发布

OK伙计们,根据Cyborgx37的想法,我已经更改了父窗体上的调用方法,如下所示:-

private void showSplashScreen()
{
    // Instantiating SplashScreen.  'using' to allow proper release of resources
    using ( SplashScreen splash = new SplashScreen() ) {
        // Displaying SplashScreen
        splash.ShowDialog();
    }
}
这将正确地释放资源。但是,我不明白为什么关闭子窗体的计时器允许正确处理资源,而单击关闭按钮则不允许。我甚至看过IL代码,这两种方法使用相同的代码。有什么想法吗?

如果使用ShowDialog,则需要手动处置资源。在这种情况下我会这么做。至于为什么它是工作时,你使用定时器,我不知道。但通常当我使用
ShowDialog
检查DialogResult,然后从父级关闭表单时。尽管像你那样使用
可以处理得更干净

SplashScreen splash = new SplashScreen(); 
DialogResult dr == splash.ShowDialog(); 

if (dr == System.Windows.Forms.DialogResult.OK)
{
    //Do something
}
else
{
    //do something else
}

splash.Close();
splash.Dispose();
关闭时未处理表单的两个条件是:(1)它是多文档界面(MDI)应用程序的一部分,并且表单不可见;(2)您已经使用ShowDialog显示了表单。在这些情况下,您将需要手动调用Dispose以将表单的所有控件标记为垃圾收集


理想情况下,您需要显示启动子表单的代码,以及您正在测试的Close方法中的代码。虽然存在对表单的引用,但它不会被垃圾回收器处理。从您发布的代码中无法判断,但这听起来像是您应该显式释放资源(而不是依赖GC)的情况。您可以在子窗体上实现
IDisposable
,然后在子窗体关闭时从父窗体显式调用
.Dispose
。在
Dispose
函数中,应该显式释放大型资源。GC几乎不可能预测。@Cyborgx37我知道这是一个资源释放的东西,但是,我不明白为什么关闭子窗体的计时器允许正确处理资源,而单击关闭按钮则不允许。我甚至看过IL代码,这两种方法使用相同的代码。有什么想法吗?实际上我已经用了你的建议来解决这个问题,所以谢谢+1个相关文档的链接。我不知道这是一个明确的要求。。。“这是我一直遵循的最佳实践。@马克·霍尔虽然我现在已经解决了这个问题,但我想我还是试试你的解决方案。GC在某些情况下正在收集,正如您经常看到的那样。然而,它仍然在不断攀升,好像GC跟不上。
using()
在100%的时间内工作。真奇怪!