我有一个Windows Form应用程序,点击某些按钮会在第二个窗体中创建对象。当用户关闭此第二个窗体时,该窗体使用的内存不会被释放(根据任务管理器)。
我尝试在退出按钮上使用this.dispose()
,this.close()
,form2 = null
在主代码中,并尝试在处理之前通过代码清除该窗体的所有控件。 这些都没有起作用,每次用户单击该按钮时,应用程序的内存使用量增加,先前实例使用的内存不会被释放。
我应该使用什么来解决这个问题?
我有一个Windows Form应用程序,点击某些按钮会在第二个窗体中创建对象。当用户关闭此第二个窗体时,该窗体使用的内存不会被释放(根据任务管理器)。
我尝试在退出按钮上使用this.dispose()
,this.close()
,form2 = null
在主代码中,并尝试在处理之前通过代码清除该窗体的所有控件。 这些都没有起作用,每次用户单击该按钮时,应用程序的内存使用量增加,先前实例使用的内存不会被释放。
我应该使用什么来解决这个问题?
调用Dispose
方法并不能清理对象使用的内存,Dispose
通常用于运行用户定义的代码以释放不会自动释放的资源,例如文件句柄、网络句柄、数据库连接等。
最可能的原因是第二个窗体将事件附加到在其外部的对象(可能是第一个窗体?),并且从未取消附加。
如果在第二个窗体中有任何事件,请在OnClose覆盖中取消附加它们-这将使第二个窗体有资格进行垃圾回收。
请注意,.NET垃圾收集器非常不可预测,它可能在清理所有已有资格进行收集的旧实例之前创建几个对象实例。要确定(而不需要使用内存分析器),一种方法是在终结器中设置断点:
public class MyForm : Form {
~MyForm() {
//breakpoint here
}
}
如果终结器被调用,则该类是OK的,否则您仍会有泄漏。您还可以给GC“一脚”,但只用于故障排除目的 - 不要在生产中使用此代码 - 通过初始化GC:GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
将上述代码放在某个在关闭和释放第二个表单之后运行的位置。您应该会在MyForm
终结器中触发断点。
Dispose
方法并不是用来释放内存的,这是由公共语言运行时的垃圾回收器负责的。Dispose方法主要用于释放其他稀缺资源,例如数据库连接和文件句柄。
一般来说,在.NET应用程序中,您不需要担心内存消耗,因为框架会为您处理。如果您需要更精细的内存控制,则应该使用提供此控制的语言(如C ++)进行开发。
听起来好像内存仍在使用,因为已释放的对象尚未被垃圾回收器回收。尝试使用GC.Collect()静态方法强制进行垃圾回收。请注意性能问题,因为这通常会暂停程序直到完成。
GC.Collect();
Dispose()
调用 Dispose(true)
。那是一个受保护的方法;你不应该调用它。 - SLaksDispose()
调用 Dispose(true)
。内部方法是实现细节,不应直接调用。 - SLaks Dispose(true);
GC.SuppressFinalize(this);
在这里,GC.SuppressFinalize(this) 是个问题,所以当你只调用 Dispose(true) 时,不会发生什么坏事情。所以如果它被限制了,可能会成为受保护的内部方法。 - WallstriderGC.SuppressFinalize()
不是问题,它只是一种垃圾回收的优化。你需要了解dispose模式的工作原理。 - SLaks