2010-05-18 63 views
4

我有一个我自己没有创建的WPF表单,所以我对WPF不太擅长。尽管如此,它的泄漏严重,高达400 MB,关闭表单并没有帮助。WPF内存泄漏

问题出在我的应用程序加载所有的图片一次。我只想加载目前可见的。它大约有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> 

回答

2

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

你如何建模公开'Thumbnail'属性的数据结构?你可以设置它,使物业需求 - 第一次访问时加载缩略图吗?也许用后备缓存(保持缩略图加载一段时间)来解决这个问题。

编辑

我可以假设的东西我不应该。在阅读我关联的第二篇文章中的评论时,我现在认为可能公开可用的ElementFlow控件版本实际上并未实现虚拟化。也许你可以登录访问'缩略图'属性,并确定是否访问不可见元素的属性。

+0

谢谢。我检查并验证Thumbnail属性的检索次数与列表中的项目一样多。是的,这是我使用的控制:)。听起来像他发现了同样的事情。实施虚拟化有多困难..? :) – 2010-05-18 21:52:13

4

当您尝试在.NET应用程序中查找内存泄漏(无论是否为WPF)时,首先要注意的是订阅事件的对象。如果对象X正在监听由对象Y引发的事件,则Y持有对X的引用。无论您实现了哪种虚拟化(或处置)方法,如果X不退订Y的事件,则X将停留在只要Y做了,就永远不会完成并垃圾收集。 (即使它实现IDisposable和显式调用Dispose就可以了。)

当你说“关闭窗体没有帮助,”这让我倍加怀疑:我想到的是有人在实现对Window对象属性对象,并且该对象已订阅某种事件。所以你关闭了窗口,但它仍然存在于对象图中,因为它的一个属性正在被引用。 (让您了解这可能有多么险恶:WinForms ToolStrip控件在显示时会订阅Windows主题更改事件。这非常棒,因为更改计算机的主题会自动反映在您的运行的UI中应用。这是不是在说,如果取消引用ToolStrip如此之大无需先设置Visible为false,它会继续接收主题改变事件,直到应用程序终止)

内存分析器可以帮助做到这一点 - 这就是我的发现我的应用程序在内存中有成千上万个对象,即使我认为所有这些对象都被破坏了。

+0

+1:我公司的WPF应用程序每次生成新页面时都会泄漏兆字节的内存,并且我们都认为这是WPF的错误。剔除了剖析器,发现每个页面都连接到静态事件处理程序,但从未取消布线,导致灾难性(并且易于修复)泄漏。 – Juliet 2010-05-19 00:51:59