关闭后,WPF窗口不会释放内存

时间:2013-01-19 04:39:37

标签: c# wpf memory window

我正在试图找出这个问题的答案:https://stackoverflow.com/questions/14379994/wpf-memory-optimization-advice

所以我创建了一个测试代码:

private void Application_Startup_1(object sender, StartupEventArgs e)
{
    ShutdownMode = System.Windows.ShutdownMode.OnExplicitShutdown;
    MainWindow window = new MainWindow();
    window.Show();
    window.Close();
    window = null;
    GC.Collect();
}

MainWindow是Visual Studio自动创建的窗口,我没有添加任何代码。 在“MainWindow window = new MainWindow();”行之前,应用程序占用4M内存。当窗口打开时,它变为13M。 即使我们关闭窗口并调用GC也不会改变。收集()

这些额外的内存用于什么以及我们如何释放它们?

3 个答案:

答案 0 :(得分:0)

您的测试代码有缺陷,有关几乎相同的情况,我的评论请参见here

您的方法稍微简单一些,但有相同的注释:

  • 将变量设置为null并调用GC.Collect是不够的。 JIT可以优化您到window = null;的分配,因为它可以清楚地看到以后不再使用该变量。此外,堆栈帧的GC报告不准确(相对于您的来源),堆栈上可能存在隐藏的副本。将测试代码移到您从中返回的单独方法中,以确保堆栈上没有剩余对MainWindow的引用。 (在确定下一个点后,从技术上讲是不必要的,但是出于完整性的考虑,我要提到它,以便人们在编写GC测试时理解这一点。)
  • 您没有给多线程WPF渲染引擎足够的时间来清理,关闭和强制GC不足以与渲染引擎同步来清理其资源

此外,您的GC.Collect调用不足以使用终结器收集对象,您需要

GC.Collect(); // find finalizable objects
GC.WaitForPendingFinalizers(); // wait until finalizers executed
GC.Collect(); // collect finalized objects

有关完整示例,请参见链接的帖子,修复后,我无法重现任何泄漏的窗口实例。

这些多余的内存是做什么用的,我们如何释放它们?

除了测试代码中的缺陷外,通过查看内存消耗,您可能还在查看错误的内容。不要只看内存,而要使用可以检查活动对象的调试器工具。 .NET运行时将预期会有更多分配,并且不会立即将内存返还给操作系统,这不是泄漏,如果运行时不使用未使用的内存,则操作系统完全有能力将未使用的内存调出。如果您重复操作,则保持增长只会存在泄漏。

答案 1 :(得分:-1)

根据https://stackoverflow.com/a/4800489/1711103的答案,您可能需要明确设置Window的父级属性。例如,在构造函数中,您可以调用:

this.Parent = this;

答案 2 :(得分:-2)

.NET垃圾收集器自动负责删除不再引用的对象。看看这个 MSDN