WPF 窗口关闭后不释放内存 [英] A WPF window doesn't release the memory after closed

查看:829
本文介绍了WPF 窗口关闭后不释放内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个测试代码:

I created a test code:

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

The MainWindow is a automatic created window by Visual Studio and I haven't add any code to it. Before the line "MainWindow window = new MainWindow();", the application occupies 4M memory. When the window is opened, it became 13M. It doesn't change even if we close the window and call the GC.Collect()

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

What are these extra memory being used for and how can we release them?

推荐答案

您的测试代码有缺陷,请参阅 此处 用于我对几乎相同场景的评论.

Your test code is flawed, see here for my comments on an almost identical scenario.

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

Yours is a bit simpler but same comments apply:

  • 将变量设置为 null 并调用 GC.Collect 是不够的.允许 JIT 优化您对 window = null; 的分配,因为它可以清楚地看到之后不再使用该变量.此外,堆栈帧的 GC 报告并不准确(相对于您的源),堆栈上可能存在隐藏的副本.将测试代码移动到您从中返回的单独方法中,以确保没有对 MainWindow 的引用留在堆栈中.(在修复下一点后,技术上没有必要,但我提到它是为了完整性,以便人们在编写 GC 测试时理解这一点.)
  • 您没有给多线程 WPF 渲染引擎清理时间,关闭和强制 GC 不足以与渲染引擎同步以清理其资源
  • setting a variable null and calling GC.Collect is not enough. The JIT is allowed to optimize your assignment to window = null; away because it can clearly see the variable is not used anymore afterwards. Furthermore GC reporting of stack frames is not exact (with respect to your source), there may be hidden copies on the stack. Move the test code into a separate method which you return from, to make sure no references to MainWindow are left on the stack. (Technically not necessary after fixing the next point, but I'm mentioning it for completeness so people understand that point when writing GC tests.)
  • you are not giving the multithreaded WPF rendering engine time to clean up, closing and forcing GC is not enough to synchronize with the rendering engine to clean up its resources

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

In addition your GC.Collect call is not enough to collect objects with finalizers, you need

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

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

See the linked post for a more complete example, after fixing it I could not reproduce any leaked window instance.

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

What are these extra memory being used for and how can we release them?

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

Besides the flaws in your test code, by looking at memory consumption you may be looking at the wrong thing. Don't look at memory alone, use debugger tools which can inspect live objects. The .NET runtime will anticipate more allocations and not give memory back to the OS immediately, this is not a leak, the OS is perfectly capable to page out unused memory if the runtime doesn't use it. A leak is only present if it keeps growing if you repeat the operation.

这篇关于WPF 窗口关闭后不释放内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆