WPF DynammicResource 泄露问题

  最近工作中,.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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值