WPF查看泄漏 - 不可见,但仍在后台呈现

时间:2017-03-15 14:00:55

标签: wpf performance memory-leaks render slowdown

有一个复杂的App,我尝试简化场景。有一个主机.exe(.NET),它包含许多控件(ActiveX,.NET,WPF) 一个控件基本上是带有项目的网格(称为“列表”),当新选择发生时,它会向另一个WPF控件发送消息(称之为“DataView”)。 “DataView”将显示当前选择的“列表”的详细信息。
当DataView收到该消息时,它将重新创建它的ViewModel,并分配给它的DataContext,因此重新创建它的View。 它的View非常复杂(XAML声明),充满了控件,模板,还包含几个Images(类型:NonDPIImage,派生自Image,带有一些基本的非重要变化,只需将其视为Image),它的Source是转换器,用于创建BitmapImages。

<Image.Source>
    <MultiBinding Converter="{StaticResource ImageConverter}">
        ...

它工作正常,但我注意到在选择更改后,“DataView”更新变得越来越慢 我进行了调试,发现在几次选择更改之后,所有先前的视图仍然在内存中,并且所有视图都在渲染其内容,因此ImageConverter会被调用所有先前的视图,因此它变得越来越慢。

我试图描述,这是我在10+选择后看到的。

enter image description here

您会看到之前的视图仍在内存中(较低的prio问题),包含图像,并且仍在渲染(高prio问题),使应用程序变得越来越慢。

我对WPF并不熟悉,我在泄漏后阅读(大多数情况下不使用DependencyProperty或类似),但这种控制非常困难,首先我要快速解决方法,以防止渲染泄漏的视图,然后再进行调查记忆问题。 (当然两者都是最好的......)

我尝试将 之前的DataContext分配给新值,将当前的View Image.Source设置为null,这样至少泄露的Image不会自动呈现,但是这会导致新的View(!)也失去了它的Image.Source,看起来WPF像一些静态数据一样缓存或共享?

由于我的第一个prio是停止“隐形渲染”,在此之后我尝试将一些模型属性设置为null,然后再创建新属性(因此它仍然会泄漏,但至少不再渲染),所以当Converter将接收属性以创建图像时,将看到它为空,并跳过渲染 但它表现得很奇怪!
对于泄漏的实例,在properties_get代码中没有命中断点,就像WPF缓存了这些值一样? 这阻止了我继续这条道路。

任何帮助/想法都会受到赞赏。

2 个答案:

答案 0 :(得分:0)

您可以发布ImageConverter代码吗? 事情是从代码创建一个图像并将其作为Image对象的源,

可以在像你这样的场景中创建它们与内存泄漏之间的强大联系。 试试这里: http://h2o2016.wpengine.com/wp-content/themes/h2o2016/images/resources/GBMBooklet.pdf

答案 1 :(得分:0)

我想我发现了这个问题:View HwndSource(AddHook())中添加了一个消息钩子,但是没有删除。这使得整个视图(参见红色矩形类)保持活力。 现在如果我在UserControl_Unloaded中调用MyHwndSource.RemoveHook(WndProc),那么View也将是GCd。