最近我注意到我的WPF项目中存在严重的内存泄漏。如果简化项目,它有一个登录表单和一个主表单。在主窗体中有1个用户控件,它由大约30个用户控件和3个按钮组成,1个用户控件有3个按钮和一个Infragistics数据网格。我使用后台工作程序每隔30秒仅为数据网格查询数据库。
在使用main form.closed注销主窗体并重新启动登录窗口后,我注意到每次ANTS内存分析器7测量增加了6-7MB。即使我有未注册的事件处理程序,设置变量为null并调用GC.Collect(),记忆泄漏仍然是一样的。我的问题是: 1.为什么关闭wpf窗口不释放内存和资源?我可以看到许多字符串(大多数来自GUI)在ANTs分析器关闭窗口后仍然在内存中。 2.我是否需要取消注册资源事件设置器定义的事件?我是否需要取消注册XAML中声明的事件? 3.从WPF memory leak,人们说我们不应该使用GC.Collect(),但我确实看到了一些改进。我们要不要使用它?
答案 0 :(得分:2)
使用WindowsFormsHost进行PictureBox控件时遇到了类似的问题。 使用WF PictureBox控件的WPF窗口无法完全释放,这就是为什么每次重新打开子窗口时我都会增加~10mb的常规值。 问题解决了,因为我开始在WPF窗口关闭时取消WFH对象。 如果你使用它,请确保清除所有WF控件。
答案 1 :(得分:0)
进入调试器,然后在立即窗口中输入:
.load C:\Windows\Microsoft.NET\Framework\v2.0.50727\sos.dll
sos.dll的路径各不相同。找出正确路径的方法是在“模块”窗格中查找mscorwks.dll。无论从哪里加载的是sos.dll的正确路径。
然后输入:
System.GC.Collect()
这将确保收集任何无法到达的内容。然后输入:
!DumpHeap -type <some-type-name>
这将显示包含地址的所有现有实例的表。您可以找到保持实例活着的内容:
!gcroot <some-address>
最初由Daniel
回答答案 2 :(得分:0)
这取决于。 WPF中的用户控件本身并不处理,因此您必须覆盖功能并在控件中允许它:
http://msdn.microsoft.com/en-us/library/system.idisposable.dispose.aspx
但是就你的观点而言,你需要至少进行一次GC.Collect(),如SlimGG建议的那样。
在大多数情况下,直接调用垃圾收集器被认为是不好的做法,因为它没有专门为您的控件调用它,而是排队等待处理的所有对象。