WPF内存泄漏

时间:2010-05-18 20:37:26

标签: .net wpf performance memory-leaks

我有一个我自己没有创建的WPF表单,所以我不擅长WPF。它虽然泄漏严重,但高达400 MB并且关闭表单无济于事。

问题在于我的应用程序一次加载所有图片。我想只加载那些可见的。这是大约300张图片,它们有点大,所以我的WPF格式可能会加载它们。

我有DataTemplate我自己的类型,其属性为Thumbnail。模板中的代码如下:

            <Image Source="{Binding Path=Thumbnail}" Stretch="Fill"/>

然后我有一个控件的网格,上面的模板作为源。此控件的代码如下所示。请提供一些关于如何优化代码的提示,并且可能只获得可见的并且只能同时加载许多控件的提示?

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Controls:ElementFlow">
                <Grid Background="{TemplateBinding Background}">
                    <Canvas x:Name="PART_HiddenPanel"
                            IsItemsHost="True"
                            Visibility="Hidden" />
                    <Viewport3D x:Name="PART_Viewport">
                        <!-- Camera -->
                        <Viewport3D.Camera>
                            <PerspectiveCamera FieldOfView="60"
                                               Position="0,1,4"
                                               LookDirection="0,-1,-4"
                                               UpDirection="0,1,0" />
                        </Viewport3D.Camera>

                        <ContainerUIElement3D x:Name="PART_ModelContainer" />

                        <ModelVisual3D>
                            <ModelVisual3D.Content>
                                <AmbientLight Color="White" />
                            </ModelVisual3D.Content>
                        </ModelVisual3D>
                <Viewport2DVisual3D
        RenderOptions.CachingHint="Cache"
        RenderOptions.CacheInvalidationThresholdMaximum="2"
        RenderOptions.CacheInvalidationThresholdMinimum="0.5"/>
                    </Viewport3D>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

3 个答案:

答案 0 :(得分:4)

当您尝试在.NET应用程序(无论是否为WPF)中查找内存泄漏时,首先要查看订阅事件的对象。

如果对象X正在侦听由对象Y引发的事件,那么Y保存对X的引用。无论您实现什么虚拟化(或处置)方法,如果X没有取消订阅Y的事件,X将保留在对象中图表只要是Y,并且永远不会最终确定并进行垃圾收集。 (即使它实现了IDisposable,你明确地在其上调用Dispose。)

当你说“关闭表单没有帮助”时,这让我倍加怀疑:我希望有人在Window对象上实现了一个对象属性,并且该对象已经订阅了一些事件类。因此,您关闭窗口,但它仍然存在于对象图中,因为正在引用其中一个属性。

(为了让您知道这可能是多么阴险:WinForms ToolStrip控件在它们变得可见时订阅Windows主题更改事件。这非常棒,因为更改计算机主题会自动反映在UI中如果你在没有先将ToolStrip设置为false的情况下取消引用Visible,它就会继续接收主题更改事件,直到应用程序终止为止。

内存分析器可以帮助解决这个问题 - 这就是我发现我的应用程序在内存中有数千个ToolStrip对象的方式,即使我认为它们都被破坏了。

答案 1 :(得分:2)

'ElementFlow'控件是否与here描述的控件相同?控件似乎是already using virtualization,所以我不希望它访问不可见项目的Thumbnail属性。

如何对暴露“缩略图”属性的数据结构进行建模?你可以设置它,以便属性需要在首次访问时加载缩略图吗?也许使用后备缓存(将缩略图加载一段时间)来实现这一点可以解决问题。

修改

我可能已经假设了一些我不应该拥有的东西。在阅读我链接的第二篇文章的评论时,我现在认为可能是公开提供的ElementFlow控件版本实际上并未实现虚拟化。也许您可以记录对“缩略图”属性的访问,并确定是否访问了不可见元素的属性。

答案 2 :(得分:0)

仅使用您的代码段很难缩小问题范围。如果您还没有,可能需要Visual Profiler