WPF DynammicResource 泄露问题

来源:互联网 发布:电视播放软件破解版 编辑:程序博客网 时间:2024/05/01 00:16

  最近工作中,.Net 4.0环境下,WPF项目发现内存泄露问题,经过一系列跟踪分析,发现是Style中资源的动态资源引起的。具体什么原因,还未搞明白,特此写出来,跟码友交流。

    先针对发现的问题,做了个小测试程序,如下。

MainWindow.xaml:

<Window x:Class="DynamicResourceLeakTest.MainWindow"        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        Title="MainWindow" Height="350" Width="525">    <Grid Name="grid" /></Window>


MainWindow.xaml.cs:

        public MainWindow()        {            InitializeComponent();            // 加载资源            var resource = new ResourceDictionary();            resource.Source = new Uri("pack://application:,,,/DynamicResourceLeakTest;component/Resources/Styles.xaml");            this.Resources.MergedDictionaries.Add(resource);            // 添加控件            var control = new Control();            control.Style = this.TryFindResource("Custom_Style") as Style;            grid.Children.Add(control);            // 定时刷新控件            var timer = new DispatcherTimer();            timer.Interval = new TimeSpan(0, 0, 0, 0, 5);            timer.Tick += (s, ee) =>            {                control.IsEnabled = !control.IsEnabled;            };            timer.Start();        }

在Resources目录下存放的是两个资源文件

本文的重点在于Resources/Resource.xaml:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">    <SolidColorBrush x:Key="CustomColor" Color="Gray" />    </ResourceDictionary>
Resources/Styles.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"                    xmlns:local="clr-namespace:DynamicResourceLeakTest">    <ResourceDictionary.MergedDictionaries>        <ResourceDictionary Source="Resource.xaml" />    </ResourceDictionary.MergedDictionaries>    <Style x:Key="Custom_Style"  TargetType="{x:Type Control}">        <Setter Property="Template">            <Setter.Value>                <ControlTemplate TargetType="{x:Type Control}">                    <Border Name="border" />                    <ControlTemplate.Triggers>                        <Trigger Property="IsEnabled" Value="False">                            <Setter Property="Background" Value="{DynamicResource CustomColor}" />                        </Trigger>                                            </ControlTemplate.Triggers>                </ControlTemplate>            </Setter.Value>        </Setter>    </Style></ResourceDictionary>
用.NET Memory Profiler 4.0 分析得到分析图如下,可见内存实例数在增加。

在overview表中,看到实例数增加首当其冲的是System.WeakReference.


双击进去看调用堆栈情况:


正是我们在定时器里周期执行的设置control.IsEnabled操作。

在Style中的Trigger中,我么修改了Background的值,但是Background这值在模板中并未用到。相反,我将模板修改,用上Background,代码:

<Border Name="border" Background="{TemplateBinding Background}"/>

这样再运行监视下,没发现内存增加。

此现象具体原因不明,望指教。


0 0