一个WPF窗口在关闭后没有释放内存

9

我创建了一个测试代码:

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窗口才会被释放。这是通过在窗口析构函数中使用debug.writeline进行跟踪的。 - evilfish
3个回答

1

你的测试代码有缺陷,可以看看这里,这是我对几乎相同场景的评论。

你的代码稍微简单一些,但是同样的评论适用:

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

另外,你的GC.Collect调用不足以收集具有finalizer的对象,你需要

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

请参阅链接的帖子以获取更完整的示例,修复后我无法再次复制任何泄漏的窗口实例。
这些额外的内存用于什么,我们如何释放它们?
除了您测试代码中的缺陷之外,通过查看内存使用情况,您可能正在关注错误的事情。不要仅查看内存,使用可以检查活动对象的调试器工具。 .NET运行时将预计进行更多分配,并且不会立即将内存返还给操作系统,这不是泄漏,如果运行时不使用它,则操作系统完全能够分页未使用的内存。只有在重复操作时它才会持续增长,才存在泄漏。

-1

这对我有用;仅实例化一个System.Windows.Window(甚至不显示它)就会将其留在内存中。将Parent设置为Application.Current.MainWindow即可解决问题。 - Rik Bradley

-3

.NET 垃圾回收器会自动处理不再被引用的对象。请查看MSDN


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接