【问题标题】:Weird scenario where my Converter doesnt get GC'd我的转换器没有得到 GC 的奇怪场景
【发布时间】:2013-03-31 20:06:00
【问题描述】:

在我的一个 wp8 应用程序中,我使用 BindingReflector 来启用转换器参数的绑定。我遇到的一个问题是,任何高于(在 XAML 中)在参数上使用绑定的转换器根本不会得到 GC。我注意到使用这种特定顺序的页面在导航到它然后返回并重复时会获得越来越多的内存。

在试图弄清楚发生了什么之后,我决定尝试更改它们在 XAML 中的顺序,使之在顶部使用反射器,问题就解决了。我想知道是否有人对此有任何解释。

当我遇到这个内存泄漏问题时,GC Roots 下的分析器显示我的转换器都在使用带有 Handle (弱引用)。不知道这是怎么发生的,但现在一旦他们发现一切都很好,并且得到了正确的 GC。

注意转换器都在同级控件中,结构基本上是这样的列表框:

<ListBox ItemsSource={Binding...}>
   <!-- ... item template like below -->
   <controlX propX={Binding xxx, converter=....}/>
   <controlY propY={Binding yyy, converter=....}/>
   ...
</ListBox>

编辑: 我创建并上传了一个简单的测试项目,你可以download the zip from here。 运行应用程序,一旦 MainPage 加载,单击将您带到 Page1.xaml 的按钮,点击返回按钮,然后再次单击将您带到 Page1.xaml 的按钮并重复此过程。

我在每个页面的标题下都包含了显示当前内存使用情况的计数器,你不会注意到那里有任何东西,但接下来的 3 个计数器是

  1. Page1 对象的当前实例计数(黄色)
  2. 随机转换器对象的当前实例计数(红色)
  3. 使用绑定反射器对象的转换器的当前实例计数(绿色)

您会注意到,虽然黄色和绿色永远不会超过 3,但当您在 ​​MainPage.xaml 和 Page1.xaml 之间来回移动时,红色会继续上升。

现在,使用 Page1.xaml 中的转换器切换 2 个按钮控件的位置,只需将它们注释掉并取消注释它们下面的那些,您会注意到所有 3 个计数器都不会超过 3。

编辑 2: 显然,这不仅仅是绑定反射器。让两个按钮使用相同的转换器将导致特定的转换器实例不被 GC。我不知道为什么会这样。。

【问题讨论】:

  • 弱引用不会阻止对象被收集。因此,拥有这些只是表明该对象尚未被 GC。
  • 另外,如果您能上传一个重现该问题的小项目,我将不胜感激。这很有趣。
  • 有趣的是,泄漏似乎与 DataTemplate 有关。只需将按钮放在页面资源中的数据模板中就足以导致泄漏,即使数据模板没有在任何地方使用。但我还没有弄清楚确切的原因是什么。

标签: memory-leaks windows-phone-8 windows-phone


【解决方案1】:

到目前为止我发现了什么:

  • 泄漏以某种方式与 DataTemplate 相关联。如果我将控件放在 DataTemplate 之外,我将无法重现它。此外,即使控件是在页面资源中未使用的 DataTemplate 中声明的,也会发生泄漏
  • 没有 GCRoot 可以解释该对象没有被垃圾回收。所以引用可能由一些内部本机对象持有。我已经注意到可能发生这种情况的情况:http://blogs.codes-sources.com/kookiz/archive/2013/02/17/wpdev-memory-leak-with-bitmapimage.aspx
  • 正如您在 cmets 中提到的,泄漏可以通过两个按钮引用同一个转换器来重现。如果两个按钮引用相同转换器类型的单独实例,则不会发生泄漏。因此,我猜 Silverlight 运行时在初始化 DataTemplate 时会以某种方式弄乱它的引用计数。

解决方法:

我有胆量认为泄漏来自在 DataTemplate 中引用一个已从模板范围之外声明的对象(在您的情况下是转换器,但它也让我想起了that similar leak involving an attached property)。在寻找在同一范围内声明转换器的方法时,我设法找到了一种解决方法:

坐下,深呼吸。打开泄漏转换器的类(在您的情况下,RandomConverter)。使其继承形式FrameworkElement。泄漏已修复。

...别问了。

这种解决方法实际上是找出内存分配问题所在的好方法。我会在接下来的几天里尝试进一步挖掘,但不要期望太高。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-04
    • 1970-01-01
    • 2015-03-26
    • 2020-09-24
    • 1970-01-01
    • 2021-03-16
    • 1970-01-01
    相关资源
    最近更新 更多