我创建了一个测试代码:
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(使用前将#替换为@)