同一个程序,换一个主题、换一个样式,可能造成内存泄露。
演示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安装不上,有知道怎么解决下面问题的请回复。