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

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

4

3 回答 3

1

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

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

  • 设置一个变量 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 运行时将预期更多的分配并且不会立即将内存归还给操作系统,这不是泄漏,如果运行时不使用它,操作系统完全能够分页出未使用的内存。仅当您重复该操作时泄漏持续增长时才会出现泄漏。

于 2020-08-30T12:22:11.360 回答
-2

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

this.Parent = this;
于 2015-06-09T18:18:49.823 回答
-3

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

于 2013-01-19T05:05:03.870 回答