WPF性能优化:Freezable 对象

这篇具有很好参考价值的文章主要介绍了WPF性能优化:Freezable 对象。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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对象的可修改克隆。为了消除克隆导致的性能开销,如果需要对对象进行动画处理,请让其保持解冻状态。

Clone和CloneCurrentValue的区别

CloneCloneCurrentValue方法都可以创建(深拷贝)解冻的副本。需要注意的是,这两个方法不拷贝未设置的属性,如果一个未设置的属性的默认值是冻结的Freezable对象,在其他解冻的拷贝中,这个属性依旧是冻结的。下表中总结了两个方法的不同之处:

操作 Clone CloneCurrentValue
复制具有表达式的依赖项属性 复制了表达式,但可能不再解析。 复制表达式的当前值,但不复制表达式本身。
复制一个动画依赖属性 复制属性的基本(非动画)值。动画不会被复制。 复制属性的当前动画值。动画不会被复制。

附加属性实现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中冻结资源(纯属探索,实际意义不大)。


我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2wt6hg8c1l0ks文章来源地址https://www.toymoban.com/news/detail-711488.html

到了这里,关于WPF性能优化:Freezable 对象的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【优化技术专题】「性能优化系列」针对Java对象压缩及序列化技术的探索之路

    序列化和反序列化 序列化就是指把对象转换为字节码; 对象传递和保存时,保证对象的完整性和可传递性。把对象转换为有字节码,以便在网络上传输或保存在本地文件中; 反序列化就是指把字节码恢复为对象; 根据字节流中保存的对象状态及描述信息,通过反序列化重建

    2024年01月22日
    浏览(57)
  • 一个Entity Framework Core的性能优化案例

    本文提供一个EF Core的优化案例,主要介绍一些EF Core常用的优化方法,以及在优化过程中,出现性能反复的时候的解决方法,并澄清一些对优化概念的误解,例如AsNoTracking并不包治百病。 本文使用的是Dotnet 6.0和EF Core 7.0。 本文主要使用一个图书和作者的案例,用于介绍优化过

    2024年02月08日
    浏览(47)
  • MySQL数据库的性能优化----(一步一个脚印)

    一、MySQL数据库的优化目标、基本原则: 1、优化目标: MySQL数据库是常见的两个瓶颈是CPU和I/O的瓶颈,无论是索引优化、还是表结构优化,参数优化,最后都可以归纳到这这两个分类中: (1)减少 I/O 次数: I/O是数据库最容易瓶颈的地方,大部分数据库操作中超过90%的时间

    2024年02月03日
    浏览(90)
  • pyDAL一个python的ORM(终) pyDAL的一些性能优化

    对于 大量数据插入时,虽然pyDAL也手册中有个方法: bulk_insert(),但是手册也说了,虽然方法上是一次可以多条数据, 如果后端数据库是关系型数据库,他转换为SQL时它是一条一条的插入的,只有在NoSQL数据库时能提速 , bulk_insert()的用法如下 ,感兴趣的看看: 那后端是关系

    2024年01月19日
    浏览(37)
  • Unity 性能优化的手段(对象池、静/动态批处理、GPU实例化、垃圾回收、LOD、LightMap)【更新中】

    目录 对象池 扩容策略 收缩策略 DrawCall DrawCall的过程 为什么减少DrawCall可以实现性能优化? 减少Draw Call的方法 静态批处理(Static Batching) 动态批处理(Dynamic Batching) GPU Instancing(GPU实例化)​​​​​​​ 贴图集 垃圾回收的优化 垃圾回收的性能影响 延迟垃圾回收 避免

    2024年02月04日
    浏览(41)
  • Redis缓存设计与性能优化【并发创建同一个缓存,解决方案:互斥锁】

    开发人员使用“缓存+过期时间”的策略既可以加速数据读写, 又保证数据的定期更新, 这种模式基本能够满足绝大部分需求。 但是有两个问题如果同时出现, 可能就会对应用造成致命的危害: 当前key是一个热点key(例如一个热门的娱乐新闻),并发量非常大。 重建缓存不

    2024年04月09日
    浏览(52)
  • 【C++】特殊类的设计(只在堆、栈创建对象,单例对象)

    🌏博客主页: 主页 🔖系列专栏: C++ ❤️感谢大家点赞👍收藏⭐评论✍️ 😍期待与大家一起进步! 实现方式: 将类的构造函数私有,拷贝构造声明成私有。防止别人调用拷贝在栈上生成对象。 提供一个静态的成员函数,在该静态成员函数中完成堆对象的创建 实现方法:

    2024年02月06日
    浏览(48)
  • 6.函数是特殊的对象2 - JS

    在第一部分中,主要总结了函数作为一个对象的常见属性( name/length )、如何自定义属性以及如何使用函数构造器( Function )。 这里总结函数作为对象的常见方法( apply/call/bind/toString )。 call 方法指定 this 并且逐个提供参数。 基本语法 thisArg ,调用 f 时指定的 this 值:

    2024年02月19日
    浏览(36)
  • 【C++系列P5】‘类与对象‘-三部曲——[对象&特殊成员](3/3)

     前言 大家好吖,欢迎来到 YY 滴 C++系列 ,热烈欢迎! 【 \\\'类与对象\\\'-三部曲】的大纲主要内容如下 : 如标题所示,本章是【 \\\'类与对象\\\'-三部曲】三章中的第三章节——对象成员章节,主要内容如下: 目录 一.const成员/成员函数 一.用const修饰this指针的好处——含权限知识点

    2024年02月06日
    浏览(44)
  • keep-alive 是 Vue 的一个内置组件,用于缓存其他组件的实例,以避免重复渲染和销毁,它可以在需要频繁切换的组件之间提供性能优化

    目录 keep-alive  使用 keep-alive 的示例代码: 手动清除组件缓存的示例代码: keep-alive 组件有以下几个优点: keep-alive 的原理: 使用 keep-alive 组件,你可以包裹需要缓存的组件,然后这些组件在切换时将会被缓存起来,而不是每次都重新创建。 使用 keep-alive 的示例代码: 我们

    2024年02月08日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包