30行WPF应用程序泄漏内存

时间:2011-01-31 15:44:38

标签: wpf xaml memory-leaks

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

在第一台计算机上,内存使用率始终保持平均值,该平均值在与动画持续时间相同的频率下略微振荡。测试程序已经运行了一个多星期而没有泄漏内存。这台计算机运行32位Windows 7。

在第二台计算机上,内存使用情况显示相同的循环行为,但每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#代码。

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

2 个答案:

答案 0 :(得分: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
            { }
        }

答案 1 :(得分:0)

它是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