Freezable是WPF中一个特殊的基类,用于创建可以冻结(Freeze)的可变对象。冻结一个对象意味着将其状态设置为只读,从而提高性能并允许在多线程环境中共享对象。

Freezable的应用

我们定义画刷资源的时候常常会这样写:

<SolidColorBrush x:Key="RedBrush" Color="Red" o:Freeze="True"/>

代码中的o:Freeze="True"其实就是使用FreezableFreeze方法冻结画刷,使之不可修改,系统不必监视该画刷对象,从而减少资源消耗。

o:Freeze="True"乍一看像附加属性,其实并不是的。Freeze属性是http://schemas.microsoft.com/winfx/2006/xaml/presentation/optionsXML命名空间中定义的唯一属性或其他编程元素。Freeze属性专门存在于此特殊命名空间中,以便在根元素声明中可以使用。处理 Freeze属性的功能专门内置于处理已编译应用程序的 XAML的XAML处理器中。

那是不是WPF中的所有资源都可以(需要)使用Freeze方法冻结来提高性能呢?

Freezable类通常用于WPF中的资源和动画,例如创建可重用的画刷、几何图形和动画。从Freezable继承的类型包括BrushTransformGeometry类。由于它们包含非托管资源,因此系统必须监视这些对象发生的修改,然后在原始对象发生更改时更新对应的非托管资源。即使实际上并未修改图形系统对象,系统仍必须消耗一些资源来监视该对象,以防更改它。

例如,假设创建一个SolidColorBrush画笔并用它来绘制按钮的背景。

<Window.Resources>
<SolidColorBrush x:Key="RedBrush" Color="Red"/>
</Window.Resources>
<Button Background="{StaticResource RedBrush}"/>

呈现按钮时,WPF图形子系统使用你提供的信息来绘制一组像素,以创建按钮的外观。尽管使用纯色画笔来描述按钮的绘制方式,但纯色画笔实际上并没有进行绘制。图形系统为按钮和画笔生成快速、低级别的对象,实际显示在屏幕上的就是这些对象。

如果要修改画笔,则必须重新生成这些低级别对象。Freezable类使画笔能够找到生成的相应低级别对象并在更改时更新它们。

注意事项

并非每个Freezable对象都可以冻结。为避免引发InvalidOperationException,请在尝试冻结Freezable对象之前检查该对象的CanFreeze属性值,以确定是否可以将其冻结。如果满足以下任一条件,则无法冻结Freezable:

  • 它具有动画属性或数据绑定属性。
  • 它具有由动态资源设置的属性。
  • 它包含无法冻结的Freezable子对象。

Freezable对象调用Freeze方法冻结后,就无法解冻。修改冻结对象属性时会引发InvalidOperationException。但是,可以使用CloneCloneCurrentValue方法创建(深拷贝)解冻的副本。如果Freezable包含其他已冻结的 Freezable对象,它们也会被克隆并变为可修改。

无论使用哪种克隆方法,动画都不会复制到新的 Freezable。

由于无法对冻结的Freezable进行动画处理,因此使用Storyboard对其进行动画处理时,动画系统会自动创建冻结的Freezable对象的可修改克隆。为了消除克隆导致的性能开销,如果需要对对象进行动画处理,请让其保持解冻状态。

附加属性实现XAML中Freeze

上文中提到o:Freeze="True"并不是通过附加属性实现,而是内置于XAML处理器中实现。我们自己也可以通过附加属性的方式实现,代码如下:

public class PresentationOptionsAttach
{
public static bool GetFreeze(Freezable freezable)
{
return (bool)freezable.GetValue(FreezeProperty);
} public static void SetFreeze(Freezable freezable, bool value)
{
freezable.SetValue(FreezeProperty, value);
} public static readonly DependencyProperty FreezeProperty =
DependencyProperty.RegisterAttached("Freeze", typeof(bool), typeof(PresentationOptionsAttach), new PropertyMetadata(false, OnFreezeChanged)); private static void OnFreezeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (DesignerProperties.GetIsInDesignMode(d)) return; if ((bool)e.NewValue)
{
Freezable freezable = d as Freezable;
if (freezable.CanFreeze)
freezable.Freeze();
}
}
}

小结

Freezable是一个我们既熟悉又陌生的类,熟悉是因为我们经常使用,陌生是因为很少关注其优化性能的机制以及需要注意的地方。本文简单介绍了Freezable优化性能的机制以及注意事项,并提供了通过附加属性的方式在XAML中冻结资源。

WPF性能优化:Freezable 对象的更多相关文章

  1. WPF性能优化经验总结

    WPF性能优化一.Rendering Tier 1. 根据硬件配置的不同,WPF采用不同的Rendering Tier做渲染.下列情况请特别注意,因为在这些情况下,即使是处于Rendering Tie ...

  2. WPF性能优化的一些建议

    尽量多使用Canvas等简单的布局元素,少使用Grid或者StackPanel等复杂的,减小开销. 少用Margin Padding尤其避免嵌套使用. 在自定义控件,尽量不要在控件的ResourceD ...

  3. Freezable 对象(WPF)

    # Freezable 对象(WPF) # > Freezable 继承自 DependencyObject,同时添加了 Freezable 方法,用于冻结对象. --- ## 冻结对象 ## ...

  4. c#+wpf项目性能优化之OutOfMemoryException解密

    近期,使用c#+wpf开发的软件准备正式投入使用了,使用前进行了大量的测试,测试后发现了一些问题,其中最让人头疼的就是软件的性能问题(稳定性). 这里的稳定性具体表现在机器的cpu占有率和内存使用情况 ...

  5. .NET性能优化-ArrayPool同时复用数组和对象

    前两天在微信后台收到了读者的私信,问了一个这样的问题,由于私信回复有字数和篇幅限制,我在这里统一回复一下.读者的问题是这样的: 大佬您好,之前读了您的文章受益匪浅,我们有一个项目经常占用 7-8GB ...

  6. WPF性能提高--MSDN学习摘要

    关于性能 一.    关于硬件加速 1.对于大多数图形硬件而言,大型图面是指达到 2048x2048 或 4096x4096 像素大小的图面. 二.    合理的布局 1.简单地说,布局是一个递归系统 ...

  7. Freezable 对象概述 | Microsoft Docs

    原文:Freezable 对象概述 | Microsoft Docs Freezable 对象概述Freezable Objects Overview 2017/03/30 本文内容 什么是可冻结的? ...

  8. EntityFramework之异步、事务及性能优化(九)

    前言 本文开始前我将循序渐进先了解下实现EF中的异步,并将重点主要是放在EF中的事务以及性能优化上,希望通过此文能够帮助到你. 异步 既然是异步我们就得知道我们知道在什么情况下需要使用异步编程,当等待 ...

  9. C#性能优化实践

    性能主要指两个方面:内存消耗和执行速度.性能优化简而言之,就是在不影响系统运行正确性的前提下,使之运行地更快,完成特定功能所需的时间更短. 本文以.NET平台下的控件产品MultiRow为例,描述C# ...

  10. C#性能优化实践【转】

    性能主要指两个方面:内存消耗和执行速度.性能优化简而言之,就是在不影响系统运行正确性的前提下,使之运行地更快,完成特定功能所需的时间更短. 本文以.NET平台下的控件产品MultiRow为例,描述C# ...

随机推荐

  1. 白嫖一个WebAPI限流解决方案

    什么是API限流: API 限流是限制用户在一定时间内 API 请求数量的过程.应用程序编程接口 (API) 充当用户和软件应用程序之间的网关.例如,当用户单击社交媒体上的发布按钮时,点击该按钮会触发 ...

  2. 曲线艺术编程 coding curves 第十四章 其它曲线(Miscellaneous Curves)

    第十四章 其它曲线(Miscellaneous Curves) 原作:Keith Peters https://www.bit-101.com/blog/2022/11/coding-curves/ ...

  3. Stable Diffusion AIGC:3步成为P图大师

    摘要:instructPix2Pix文字编辑图片是一种纯文本编辑图像的方法,用户提供一张图片和文本编辑指令,告诉模型要做什么,模型根据编辑指令编辑输入的图像,最终输出用户想要的图像. 本文分享自华为云 ...

  4. 【Springboot】SpringBoot-Admin 服务监控+告警通知

    SpringBoot-Admin 服务监控 简单介绍 Spring Boot Actuator 是 Spring Boot 自带的一个功能模块, 提供了一组已经开箱即用的生产环境下常用的特性和服务,比 ...

  5. 【SpringBoot】 集成 Ehcache

    SpringBoot ehcache 缓存 简介 EhCache 是一个纯 Java 的进程内缓存框架,具有快速.精干等特点, 是 Hibernate 中默认CacheProvider.Ehcache ...

  6. 【Docker】迷你使用手册

    一.安装与配置 安装: # Centos7 yum install docker 启动 & 设为开机启动: systemctl start docker.service systemctl e ...

  7. influxdb 保留策略

    转载请注明出处: InfluxDB 中的保留策略用于定义时间序列数据在数据库中的保留期限.保留策略决定了数据在 InfluxDB 中的存储持续时间和精度.以下是 InfluxDB 的保留策略类型以及如 ...

  8. linux内核编译体验篇(一)

    文章目录 一. 准备环境 二. 获取内核源码 三. 交叉编译工具链的配置 1. 博友们常用安装方法链接 2. 公司常用的交叉工具链使用方法 四. 内核解压以及如何打补丁 五. 内核基本配置 1. 编译 ...

  9. 【译】Visual Studio 2022 中的 Web API 开发

    在 Visual Studio 2022 中,Web 开发人员的主要场景之一是使用 ASP.NET Core 创建 Web API.在 Visual Studio 2022 17.6 的最新预览版中, ...

  10. 西门子HMI切换页面时的指示功能

    怎么样才能做到像这样按下切换界面的按钮,切换过去之后对应的切换按钮还进行高亮指示呢? 首先我们要先新建模板,把我们的画面拖拽到模板里就会形成按钮 在画面的"属性"中 在属性中选上我 ...