我有一个简单的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#代码。
有没有人可以解释为什么这么简单的程序会泄漏内存?
答案 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