按钮单击导致子窗体不被释放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%的时间内工作。真奇怪!