在我的一个 wp8 应用程序中,我使用BindingReflector来启用对转换器参数的绑定。我遇到的一个问题是,任何高于(在 XAML 中)在参数上使用绑定的转换器根本不会被 GC。我注意到使用此特定顺序的页面在导航到它然后返回并重复时会获得越来越多的内存。
在试图弄清楚发生了什么之后,我决定尝试更改它们在 XAML 中的顺序,使之在顶部使用反射器,问题就解决了。我想知道是否有人对此有任何解释。
当我遇到这个内存泄漏问题时,在GC Roots下的分析器显示我的转换器都在使用带有Handle (WeakRef)的反射器引用(不是直接)转换器。不知道怎么会发生这种情况,但是现在一旦它们出现故障,一切都很好,并且可以正确地进行 GC。
请注意,转换器都在兄弟控件中,结构基本上是这样的列表框:
<ListBox ItemsSource={Binding...}>
<!-- ... item template like below -->
<controlX propX={Binding xxx, converter=....}/>
<controlY propY={Binding yyy, converter=....}/>
...
</ListBox>
编辑: 我创建并上传了一个简单的测试项目,您可以从这里下载 zip。运行应用程序,一旦 MainPage 加载,单击将您带到 Page1.xaml 的按钮,点击后退按钮,然后再次单击将您带到 Page1.xaml 的按钮并重复此过程。
我在每个页面的标题下都包含了显示当前内存使用情况的计数器,你不会注意到那里的任何东西,但接下来的 3 个计数器是
- Page1 对象的当前实例计数(黄色)
- 随机转换器对象的当前实例计数(红色)
- 使用绑定反射器对象的转换器的当前实例计数(绿色)
您会注意到,虽然黄色和绿色永远不会超过 3,但当您在 MainPage.xaml 和 Page1.xaml 之间来回切换时,红色会继续上升。
现在,使用 Page1.xaml 中的转换器切换 2 个按钮控件的位置,只需将它们注释掉并取消注释它们下面的那些,您会注意到所有 3 个计数器都不会超过 3。
编辑2: 显然这不仅仅是绑定反射器。让两个按钮使用相同的转换器将导致特定的转换器实例不被 GC。我不知道为什么会这样。。