30行WPF应用程序内存泄漏

发布于 2024-10-15 09:37:23 字数 2016 浏览 2 评论 0原文

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

在第一台计算机上,内存使用量始终保持平均值,并以与动画持续时间相同的频率轻微振荡。测试程序已可靠运行一周多,没有出现内存泄漏。这台计算机运行的是 Windows 7 32 位。

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

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

相同的已编译 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# 代码。

有谁有任何可能的解释为什么这么简单的程序会泄漏内存?

I have a simple WPF application consisting of a Window with an orange rectangle and a continuous animation which changes a blur radius which is applied to the rectangle. This application is currently soak testing on two computers in order to diagnose a memory leak related to WPF in a larger program.

On the first computer, the memory usage is consistently maintaining an average which oscillates slightly at the same frequency as the animation duration. The test program has been running reliably for over a week without leaking memory. This computer is running windows 7 32-bit.

On the second computer, the memory usage is showing the same cyclic behaviour, however ~ every 90 seconds the memory usage is increasing by around 100kb. This extra increase is never reclaimed for as long as the application is running. I have previously run this program until the entire system memory is consumed by this one application! An animated glow on a rectangle consuming 4gb of ram! This computer is running windows 7 embedded 32-bit.

There is a significant hardware difference between the two platforms, however both systems are running the latest drivers available for their respective hardware.

The same compiled exe is on both computers running without debuggers attached. The XAML code for the application is included below:

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

This code was built against .net Framework 4.0. There is no C# code behind this XAML.

Does anyone have any possible explanation as to why a program this simple is leaking memory?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

为你拒绝所有暧昧 2024-10-22 09:37:23

启用软件渲染修复了该泄漏。在每个 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
            { }
        }

Enabling software rendering has fixed the leak. In each Window_Loaded event I'm now enabling software rendering using the following code:

public static void EnableSoftwareRendering(Visual visual)
        {
            try
            {
                HwndSource source = PresentationSource.FromVisual(visual) as HwndSource;
                HwndTarget target = source.CompositionTarget;
                target.RenderMode = RenderMode.SoftwareOnly;
            }
            catch
            { }
        }
不语却知心 2024-10-22 09:37:23

这是一个事件处理程序泄漏

您的 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

It is an Event handlers leak.

One of your StoryBoard handler subscribes to FrameworkElement.Loaded and will be retained to the end.

I tried to remove BeginStoryBoard like this:

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

But it does not work. So I have no idea how to fix it till now.

The following is the trace of the handler from dotMemory.

System.Windows.Media.Animation.BeginStoryboard._inheritanceContext ->
System.Windows.EventTrigger._routedEventHandler ->
System.Windows.RoutedEventHandler._target ->
System.Windows.EventTrigger+EventTriggerSourceListener
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文