Silverlight内存泄露(八)样式
同一个程序,换一个主题、换一个样式,可能造成内存泄露。
演示Sytle引起的内存泄露
这一系列写到八了,将要结束,还没有一个直观例子说不过去,样式发生内存问题最难找也最隐蔽,做了小例子说明内存泄露问题。
例子下载:
例子中ProgressBar样式引起内存泄露,为直观每次导航分配50M内存。
a) 继续使用ANTS检测内存问题,但ANTS属于收费软件
b) 也可使用免费的进程浏览器,启动 Process Explorer.,在sllauncher.exe进程右击,选择属性,在Home、About间导航。
每次导航内存增加50M
注释掉ProgressBar样式后,内存不增加。
查找内存泄露
给程序更换样式后发现,View不能释放,没导航内存都增加一个View实例。查看其中一个内存关系图,如下:
可看到某个动画的引用不能释放。造成View不能释放
ProgressBar样式造成内存泄露
产生内存泄露的样式:
<!--progressbar 内存泄露-->
<Style TargetType="ProgressBar">
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="Maximum" Value="100" />
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ProgressBar">
<Grid x:Name="Root">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Determinate"/>
<VisualState x:Name="Indeterminate">
<Storyboard>
<ObjectAnimationUsingKeyFrames BeginTime="0"
Storyboard.TargetName="ProgressBarRootGrid"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames BeginTime="0"
Storyboard.TargetName="ProgressBarIndeterminateRootGrid"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation Storyboard.TargetName="tr" Storyboard.TargetProperty="X"
Duration="0:0:2" To="0.8" AutoReverse="True" RepeatBehavior="Forever">
<DoubleAnimation.EasingFunction>
<QuadraticEase EasingMode="EaseInOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="gs2" Storyboard.TargetProperty="Offset"
BeginTime="0:0:0" Duration="0:0:4"
RepeatBehavior="Forever">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="0.1"/>
<DiscreteObjectKeyFrame KeyTime="0:0:2" Value="0"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="gs3" Storyboard.TargetProperty="Offset"
BeginTime="0:0:0" Duration="0:0:4"
RepeatBehavior="Forever">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="0.2"/>
<DiscreteObjectKeyFrame KeyTime="0:0:2" Value="0.1"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="ProgressBarTrack" CornerRadius="4"
Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}" />
<Grid x:Name="ProgressBarRootGrid" >
<Rectangle HorizontalAlignment="Left" x:Name="ProgressBarIndicator"
Margin="3" RadiusX="3" RadiusY="3"
Fill="{TemplateBinding Foreground}"/>
</Grid>
<Grid x:Name="ProgressBarIndeterminateRootGrid" Visibility="Collapsed">
<Rectangle Margin="3" RadiusX="3" RadiusY="3" >
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0 0.5" EndPoint="1 0.5">
<LinearGradientBrush.RelativeTransform>
<TranslateTransform x:Name="tr" X="0"/>
</LinearGradientBrush.RelativeTransform>
<GradientStop x:Name="gs0" Offset="0" Color="Transparent"/>
<GradientStop x:Name="gs1" Offset="0" Color="Transparent"/>
<GradientStop x:Name="gs2" Offset="0" Color="#CCCCFF"/>
<GradientStop x:Name="gs3" Offset="0.2" Color="#CCCCFF"/>
<GradientStop x:Name="gs4" Offset="0.2" Color="Transparent"/>
<GradientStop x:Name="gs5" Offset="1" Color="Transparent"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="ProgressBar">
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="Maximum" Value="100" />
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ProgressBar">
<Grid x:Name="Root">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Determinate"/>
<VisualState x:Name="Indeterminate">
<Storyboard>
<ObjectAnimationUsingKeyFrames BeginTime="0"
Storyboard.TargetName="ProgressBarRootGrid"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames BeginTime="0"
Storyboard.TargetName="ProgressBarIndeterminateRootGrid"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation Storyboard.TargetName="tr" Storyboard.TargetProperty="X"
Duration="0:0:2" To="0.8" AutoReverse="True" RepeatBehavior="Forever">
<DoubleAnimation.EasingFunction>
<QuadraticEase EasingMode="EaseInOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="gs2" Storyboard.TargetProperty="Offset"
BeginTime="0:0:0" Duration="0:0:4"
RepeatBehavior="Forever">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="0.1"/>
<DiscreteObjectKeyFrame KeyTime="0:0:2" Value="0"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="gs3" Storyboard.TargetProperty="Offset"
BeginTime="0:0:0" Duration="0:0:4"
RepeatBehavior="Forever">
<DiscreteObjectKeyFrame KeyTime="0:0:0" Value="0.2"/>
<DiscreteObjectKeyFrame KeyTime="0:0:2" Value="0.1"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="ProgressBarTrack" CornerRadius="4"
Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}" />
<Grid x:Name="ProgressBarRootGrid" >
<Rectangle HorizontalAlignment="Left" x:Name="ProgressBarIndicator"
Margin="3" RadiusX="3" RadiusY="3"
Fill="{TemplateBinding Foreground}"/>
</Grid>
<Grid x:Name="ProgressBarIndeterminateRootGrid" Visibility="Collapsed">
<Rectangle Margin="3" RadiusX="3" RadiusY="3" >
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0 0.5" EndPoint="1 0.5">
<LinearGradientBrush.RelativeTransform>
<TranslateTransform x:Name="tr" X="0"/>
</LinearGradientBrush.RelativeTransform>
<GradientStop x:Name="gs0" Offset="0" Color="Transparent"/>
<GradientStop x:Name="gs1" Offset="0" Color="Transparent"/>
<GradientStop x:Name="gs2" Offset="0" Color="#CCCCFF"/>
<GradientStop x:Name="gs3" Offset="0.2" Color="#CCCCFF"/>
<GradientStop x:Name="gs4" Offset="0.2" Color="Transparent"/>
<GradientStop x:Name="gs5" Offset="1" Color="Transparent"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
结论
a) 估计是Silverlight4bug,silverlight5没测试。
b) 慎用第三方样式
安装Silverlight5的问题
Silverlight5安装不上,有知道怎么解决下面问题的请回复。