【发布时间】: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 个计数器是
- Page1 对象的当前实例计数(黄色)
- 随机转换器对象的当前实例计数(红色)
- 使用绑定反射器对象的转换器的当前实例计数(绿色)
您会注意到,虽然黄色和绿色永远不会超过 3,但当您在 MainPage.xaml 和 Page1.xaml 之间来回移动时,红色会继续上升。
现在,使用 Page1.xaml 中的转换器切换 2 个按钮控件的位置,只需将它们注释掉并取消注释它们下面的那些,您会注意到所有 3 个计数器都不会超过 3。
编辑 2: 显然,这不仅仅是绑定反射器。让两个按钮使用相同的转换器将导致特定的转换器实例不被 GC。我不知道为什么会这样。。
【问题讨论】:
-
弱引用不会阻止对象被收集。因此,拥有这些只是表明该对象尚未被 GC。
-
另外,如果您能上传一个重现该问题的小项目,我将不胜感激。这很有趣。
-
有趣的是,泄漏似乎与 DataTemplate 有关。只需将按钮放在页面资源中的数据模板中就足以导致泄漏,即使数据模板没有在任何地方使用。但我还没有弄清楚确切的原因是什么。
标签: memory-leaks windows-phone-8 windows-phone