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

2024-05-10

我创建了一个测试代码:

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

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


您的测试代码有缺陷,请参阅here https://stackoverflow.com/questions/63586833/window-object-not-released-after-being-closed-even-after-gc-collect-and-waitfor我对一个几乎相同的场景的评论。

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

  • 设置变量 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 运行时将预期更多分配,并且不会立即将内存返还给操作系统,这不是泄漏,如果运行时不使用未使用的内存,操作系统完全能够调出未使用的内存。仅当出现以下情况时才存在泄漏不断增长如果重复该操作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WPF 窗口关闭后不会释放内存 的相关文章

随机推荐