我的WPF导航中是否有内存泄漏?

时间:2009-12-17 22:31:21

标签: .net wpf memory-leaks

我正在寻找一个寻找内存泄漏的WPF应用程序(使用ANTS Memory Profiler 5.1),并且我不断看到一些页面和控件在不应该占用时占用内存。

所以我转到对象保留图并看看是什么让它们保持不变,我会在每一页都看到这一点:

Object Retention Graph http://img683.imageshack.us/img683/3013/ants.jpg

问题是,我在每个页面上都将KeepAlive设置为false,并且我认为用户控件上不存在这样的属性。

谁能告诉我应该找什么?这甚至是内存泄漏还是WPF应用程序的正常行为?

2 个答案:

答案 0 :(得分:8)

是的,根据您提供的内容,您有内存泄漏。当你找到引用链,并且它不在你的代码中时,最简单的方法就是... Reflector。

图片说:JournalEntryKeepAlive._keepAliveRoot字段包含对象的引用。让我们进入Reflector,看看这个家伙是如何与我们的对象挂钩的。

这次很简单,所有跟踪都会导致NavigationService.MakeJournalEntry()功能,然后导致NavigationService.IsContentKeepAlive()。这是:

internal bool IsContentKeepAlive()
{
    bool keepAlive = true;
    DependencyObject dependencyObject = this._bp as DependencyObject;
    if (dependencyObject != null)
    {
        keepAlive = JournalEntry.GetKeepAlive(dependencyObject);
        if (!keepAlive)
        {
            PageFunctionBase base2 = dependencyObject as PageFunctionBase;
            bool flag2 = !this.CanReloadFromUri;
            if ((base2 == null) && flag2)
            {
                keepAlive = true;
            }
        }
    }
    return keepAlive;
}

现在您了解规则。如果出现以下情况,对象将保留在内存中:

  • 它不是依赖对象;
  • 附加的属性JournalEntry.KeepAlive是真的;
  • 它不是PageFunction,也不能从Uri重新加载。

在调查之后,可能值得阅读有关MSDN上JournalEntry.KeepAlive属性的更多信息。

这种策略帮助我找到了许多与记忆相关的昆虫。希望它也能帮到你:)。

PS:如果您在查找此特定泄漏时遇到问题,可以粘贴最少的代码示例,以便我们重现它并为您提供更合适的答案。

干杯, Anvaka

答案 1 :(得分:5)

我有与蚂蚁记忆分析器相同的问题和相同的图表。 该应用程序使用NavigationWindow来托管一些WPF页面,并使用此代码隐藏进行导航:

NavigationService.Navigate( new Page1());

问题是由日志保存在内存中的多个页面创建的,无法进行垃圾回收。

我所做的是用普通窗口替换NavigationWindow,使用UserControls替换Pages并在窗口内交换用户控件,就像它们是页面一样。 关于如何在谷歌中执行此操作有很多示例。 删除所有NavigationService.Navigate调用后,我终于可以使用Ants内存分析器对所有已关闭的页面进行垃圾收集。