【问题标题】:30 line WPF Application Leaking Memory30 行 WPF 应用程序泄漏内存
【发布时间】:2011-01-31 15:44:37
【问题描述】:

我有一个简单的 WPF 应用程序,它由一个带有橙色矩形的窗口和一个连续动画组成,该动画改变了应用于矩形的模糊半径。此应用程序目前正在两台计算机上进行浸泡测试,以便在更大的程序中诊断与 WPF 相关的内存泄漏。

在第一台计算机上,内存使用率始终保持在与动画持续时间相同的频率上轻微波动的平均值。测试程序已经可靠运行了一个多星期,没有泄漏内存。这台电脑运行的是 windows 7 32 位。

在第二台计算机上,内存使用量表现出相同的循环行为,但是 ~ 每 90 秒内存使用量增加约 100kb。只要应用程序正在运行,这种额外的增加就永远不会回收。我之前运行过这个程序,直到整个系统内存都被这个应用程序占用!一个消耗 4GB 内存的矩形上的动画发光!这台计算机运行的是 32 位嵌入式 Windows 7。

两个平台之间存在显着的硬件差异,但是两个系统都运行适用于各自硬件的最新驱动程序。

相同的已编译 exe 在两台计算机上运行,​​但未连接调试器。应用程序的 XAML 代码如下:

<Window
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 x:Class="WpfAnimation.MainWindow"
 x:Name="Window"
 Title="MainWindow"
 Width="640" Height="480">
 <Window.Resources>
  <Storyboard x:Key="Flash" AutoReverse="True" RepeatBehavior="Forever" FillBehavior="Stop">
   <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Effect).(BlurEffect.Radius)" Storyboard.TargetName="rectangle">
    <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
    <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="15">
     <EasingDoubleKeyFrame.EasingFunction>
      <ElasticEase EasingMode="EaseOut"/>
     </EasingDoubleKeyFrame.EasingFunction>
    </EasingDoubleKeyFrame>
   </DoubleAnimationUsingKeyFrames>
  </Storyboard>
 </Window.Resources>
 <Window.Triggers>
  <EventTrigger RoutedEvent="FrameworkElement.Loaded">
   <BeginStoryboard Storyboard="{StaticResource Flash}"/>
  </EventTrigger>
 </Window.Triggers>

 <Grid x:Name="LayoutRoot">
  <Rectangle x:Name="rectangle" Fill="#FFFFA400" Margin="113,93,125,101" Stroke="Red" RadiusX="10" RadiusY="10" StrokeThickness="5">
   <Rectangle.Effect>
    <BlurEffect KernelType="Box" Radius="0"/>
   </Rectangle.Effect>
  </Rectangle>
 </Grid>
</Window>

此代码是针对 .net Framework 4.0 构建的。此 XAML 背后没有 C# 代码。

有没有人能解释为什么这么简单的程序会泄漏内存?

【问题讨论】:

  • 介意实际发布 XAML 吗? :)
  • 我敢打赌问题出在显卡驱动上。
  • 罗伯特,看来你一针见血了。我昨晚在启用软件渲染的情况下开始运行测试。在 12 小时内,软件渲染的应用程序已获得 2mb 的内存使用量。同时,支持 3D 的副本目前为 130mb。它们都以 45mb 的内存使用量开始。英特尔显卡驱动程序就这么多!第一台正常运行的计算机(上面提到的)有一张带有最新驱动程序的 ATI 卡。

标签: wpf xaml memory-leaks


【解决方案1】:

启用软件渲染已修复泄漏。在每个 Window_Loaded 事件中,我现在使用以下代码启用软件渲染:

public static void EnableSoftwareRendering(Visual visual)
        {
            try
            {
                HwndSource source = PresentationSource.FromVisual(visual) as HwndSource;
                HwndTarget target = source.CompositionTarget;
                target.RenderMode = RenderMode.SoftwareOnly;
            }
            catch
            { }
        }

【讨论】:

  • 我很快就会对此进行测试。知道为什么这解决了这个问题吗?
  • 根据问题本身的 cmets,我认为这是图形驱动程序的问题。切换到软件渲染绕过了容易发生内存泄漏的驱动程序。
【解决方案2】:

这是一个Event handlers leak

您的 StoryBoard 处理程序之一订阅了FrameworkElement.Loaded,并将保留到最后。

我试图像这样删除BeginStoryBoard

    <EventTrigger RoutedEvent="UserControl.Unloaded"  SourceName="CellControl">
        <RemoveStoryboard BeginStoryboardName="MouseEnterStoryBoard"/>
    </EventTrigger>

但它不起作用。所以直到现在我都不知道如何解决它。

以下是来自dotMemory的处理程序跟踪。

System.Windows.Media.Animation.BeginStoryboard._inheritanceContext ->
System.Windows.EventTrigger._routedEventHandler ->
System.Windows.RoutedEventHandler._target ->
System.Windows.EventTrigger+EventTriggerSourceListener

【讨论】:

  • 你是如何解决这个问题的?
猜你喜欢
  • 2010-11-27
  • 2011-03-21
  • 2012-04-30
  • 1970-01-01
  • 2016-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多