在我的C#Winforms应用程序中,我有以下代码(显示的代码最少)
Form1是用户用来做事情的主要应用程序。Form2显示一个帮助文件,解释如何使用Form1上的功能来做事情。我希望用户能够显示(无模式)和关闭帮助文件,只要Form1是可见的。
我还担心用户打开和关闭Form2时可能发生的内存泄漏。因此,当用户关闭Form2时,它会引发Form1订阅的事件。当调用Form1事件方法时,它会调用Form2上的Dispose(),将Form2对象设置为null并调用垃圾收集器。
这是否会消除用户打开和关闭Form2时导致内存泄漏的可能性?是否有些过头?是否有更好的方法来确保在关闭Form2时进行垃圾回收?***我不希望依赖Windows在以后决定***时执行垃圾回收
- 更新**
Jimi指出,我不需要为Form2 Closed事件定制事件处理程序。他是对的。在我的Form1类中,我现在为Form2使用标准的FormClosedEventHandler。然而,代码本身几乎保持不变。然而,当我删除对GC.Collect()的调用时,我看到了使用任务管理器时内存泄漏的迹象。
以下是我的数据:
Run #1. Form2_FormClosed method has:
------------------------------------
f_HelpForm.Dispose();
f_HelpForm = null;
GC.Collect();
Start App
Task Manager Memory for app: 6.7 MB
Open and Close Form2 20 times
Task Manager Memory for app: 8.2 MB
Run #2. Form2_FormClosed method has:
------------------------------------
f_HelpForm.Dispose();
f_HelpForm = null;
//GC.Collect();
Start App
Task Manager Memory for app: 6.9 MB
Open and Close Form2 20 times
Task Manager Memory for app: 18.9 MB
Run #3. Form2_FormClosed method has:
------------------------------------
//f_HelpForm.Dispose();
f_HelpForm = null;
//GC.Collect();
Start App
Task Manager Memory for app: 6.9 MB
Open and Close Form2 20 times
Task Manager Memory for app: 18.1 M
如果不调用GC.Collect(),无论是否调用Dispose(),与调用GC.collect()的代码相比,内存占用量都会增加100%。
我听到你们说的了,但是..........我想我会将代码保留在"Run#1"配置中
- 密码**
- 注意:我承认设置form2 = null对后台垃圾收集有直接影响。但是,我设置form2 = null的目的是向
Form2Button_Click
方法提供一个信号,它可以使用该信号来决定是否示例化Form2对象 *
public partial class Form1 : Form
{
Form2 form2;
public Form1()
{
form2 = null;
}
private void Form2Button_Click(object sender, EventArgs e)
{
if (form2 == null)
{
form2 = new ClsHelpForm(this);
form2.Form2Closed += Form2_FormClosed;
}
form2.Select();
form2.Show();
}
//When this user clicks the Help button on Form1, this method is invoked
private void Form2_FormClosed(object sender, EventArgs e)
{
form2.Form2Closed -= Form2_FormClosed;
form2.Dispose();
form2 = null;
GC.Collect();
}
{
public partial class Form2 : Form
{
public event EventHandler Form2Closed;
public Form2()
{
}
//When the user clicks the "X" button on Form2, this method is invoked
private void Form2_FormClosed(object sender, Form2EventArgs e)
{
Form2Closed?.Invoke(this, EventArgs.Empty);
}
}
3条答案
按热度按时间lnvxswe21#
我还担心在用户打开和关闭Form2时可能发生的内存泄漏。
为什么要担心内存泄漏?在没有问题的迹象时不要尝试优化。只要Form2及其所有子对象在调用Dispose时实际清理资源,就不应该有内存泄漏。
有没有更好的方法来确保在Form2关闭时进行垃圾收集?我不想依赖Windows在以后决定这样做时进行垃圾收集
这看起来像是不必要的妄想症。只要确保Form2在其Dispose方法中进行清理,并让垃圾收集自然发生。除了删除GC.Collect()调用之外,一切看起来都很好。
wvt8vs2t2#
Form2
的成员示例不会占用堆上的很多空间,而且似乎没有什么理由在每次用户想要显示它时创建和销毁它的Handle。为什么不在应用程序关闭之前阻止
Form2
句柄的破坏呢?当表格2循环(通过自动化)100次时,监测过程内存显示GC为零,并且与所示次数无直接相关性。
其中:
b5lpy0ml3#
如果你把垃圾放在厨房垃圾桶里,5分钟后垃圾还在那里,这并不意味着垃圾会永远在那里。这只是意味着垃圾还没有被清空。一旦垃圾桶装满,它最终会被清空。“泄漏”是指如果你把垃圾放在地板上,在这种情况下,当垃圾桶装满时,它就不会被捡起来。(不是一个完美的类比,因为有人(希望)会在某个时候捡起来,但你明白这个想法)
您的观察结果可能会显示100%的增长,因为没有内存压力需要进行收集。只有当内存“从未”被GC释放时,才会发生内存泄漏,强制垃圾收集无法修复这种情况。内存泄漏的一个示例是对非托管资源的引用,该资源在释放(未关闭)窗体时没有释放。
自己调用
GC.Collect
并不能修复内存泄漏--它只是在系统需要的时候 * 更早地 * 清理内存。