【问题标题】:A WPF window doesn't release the memory after closedWPF 窗口关闭后不释放内存
【发布时间】:2013-01-02 21:14:53
【问题描述】:

我创建了一个测试代码:

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.Collect() 也不会改变

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

【问题讨论】:

  • 我也有同样的问题。我的有点不同,因为我的 wpf 窗口是由另一个程序集创建的。我创建了一个新窗口很多,我可以看到内存上升。只有当程序集关闭时,我所有的 wpf 窗口才会被释放。由 windows 解构器中的 debug.writeline 跟踪

标签: c# wpf memory window


【解决方案1】:

您的测试代码有缺陷,请参阅here 了解我的 cmets 在几乎相同的情况下。

你的有点简单,但同样适用:

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

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

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

查看链接的帖子以获得更完整的示例,修复后我无法重现任何泄漏的窗口实例。

这些额外的内存有什么用,我们如何释放它们?

除了测试代码中的缺陷之外,通过查看内存消耗,您可能会看到错误的东西。不要只看内存,使用可以检查活动对象的调试器工具。 .NET 运行时将预期更多的分配并且不会立即将内存还给操作系统,这不是泄漏,如果运行时不使用它,操作系统完全能够分页出未使用的内存。仅当您重复操作继续增长时才会出现泄漏。

【讨论】:

    【解决方案2】:

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

    this.Parent = this;
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 2020-01-04
        • 2016-10-03
        • 2010-10-14
        • 2012-03-09
        • 2012-06-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-20
        相关资源
        最近更新 更多