翼度科技»论坛 编程开发 .net 查看内容

WPF性能优化:Freezable 对象

8

主题

8

帖子

24

积分

新手上路

Rank: 1

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

我们定义画刷资源的时候常常会这样写:
  1. [/code]代码中的o:Freeze="True"其实就是使用Freezable的 Freeze方法冻结画刷,使之不可修改,系统不必监视该画刷对象,从而减少资源消耗。
  2. [indent]o:Freeze="True"乍一看像附加属性,其实并不是的。Freeze属性是http://schemas.microsoft.com/winfx/2006/xaml/presentation/optionsXML命名空间中定义的唯一属性或其他编程元素。Freeze属性专门存在于此特殊命名空间中,以便在根元素声明中可以使用。处理 Freeze属性的功能专门内置于处理已编译应用程序的 XAML的XAML处理器中。
  3. [/indent]那是不是WPF中的所有资源都可以(需要)使用Freeze方法冻结来提高性能呢?
  4. Freezable类通常用于WPF中的资源和动画,例如创建可重用的画刷、几何图形和动画。从Freezable继承的类型包括Brush、Transform和Geometry类。由于它们包含非托管资源,因此系统必须监视这些对象发生的修改,然后在原始对象发生更改时更新对应的非托管资源。即使实际上并未修改图形系统对象,系统仍必须消耗一些资源来监视该对象,以防更改它。
  5. 例如,假设创建一个SolidColorBrush画笔并用它来绘制按钮的背景。
  6. [code]<Window.Resources>
  7.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  8. </Window.Resources>
  9. <Button Background="{StaticResource RedBrush}"/>
复制代码
呈现按钮时,WPF图形子系统使用你提供的信息来绘制一组像素,以创建按钮的外观。尽管使用纯色画笔来描述按钮的绘制方式,但纯色画笔实际上并没有进行绘制。图形系统为按钮和画笔生成快速、低级别的对象,实际显示在屏幕上的就是这些对象。
如果要修改画笔,则必须重新生成这些低级别对象。Freezable类使画笔能够找到生成的相应低级别对象并在更改时更新它们。
注意事项

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

  • 它具有动画属性或数据绑定属性。
  • 它具有由动态资源设置的属性。
  • 它包含无法冻结的Freezable子对象。
Freezable对象调用Freeze方法冻结后,就无法解冻。修改冻结对象属性时会引发InvalidOperationException。但是,可以使用Clone或CloneCurrentValue方法创建(深拷贝)解冻的副本。如果Freezable包含其他已冻结的 Freezable对象,它们也会被克隆并变为可修改。
无论使用哪种克隆方法,动画都不会复制到新的 Freezable。
由于无法对冻结的Freezable进行动画处理,因此使用Storyboard对其进行动画处理时,动画系统会自动创建冻结的Freezable对象的可修改克隆。为了消除克隆导致的性能开销,如果需要对对象进行动画处理,请让其保持解冻状态。
附加属性实现XAML中Freeze

上文中提到o:Freeze="True"并不是通过附加属性实现,而是内置于XAML处理器中实现。我们自己也可以通过附加属性的方式实现,代码如下:
  1. public class PresentationOptionsAttach{<Window.Resources>
  2.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  3. </Window.Resources>
  4. <Button Background="{StaticResource RedBrush}"/>public static bool GetFreeze(Freezable freezable)<Window.Resources>
  5.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  6. </Window.Resources>
  7. <Button Background="{StaticResource RedBrush}"/>{<Window.Resources>
  8.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  9. </Window.Resources>
  10. <Button Background="{StaticResource RedBrush}"/><Window.Resources>
  11.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  12. </Window.Resources>
  13. <Button Background="{StaticResource RedBrush}"/>return (bool)freezable.GetValue(FreezeProperty);<Window.Resources>
  14.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  15. </Window.Resources>
  16. <Button Background="{StaticResource RedBrush}"/>}<Window.Resources>
  17.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  18. </Window.Resources>
  19. <Button Background="{StaticResource RedBrush}"/>public static void SetFreeze(Freezable freezable, bool value)<Window.Resources>
  20.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  21. </Window.Resources>
  22. <Button Background="{StaticResource RedBrush}"/>{<Window.Resources>
  23.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  24. </Window.Resources>
  25. <Button Background="{StaticResource RedBrush}"/><Window.Resources>
  26.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  27. </Window.Resources>
  28. <Button Background="{StaticResource RedBrush}"/>freezable.SetValue(FreezeProperty, value);<Window.Resources>
  29.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  30. </Window.Resources>
  31. <Button Background="{StaticResource RedBrush}"/>}<Window.Resources>
  32.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  33. </Window.Resources>
  34. <Button Background="{StaticResource RedBrush}"/>public static readonly DependencyProperty FreezeProperty =<Window.Resources>
  35.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  36. </Window.Resources>
  37. <Button Background="{StaticResource RedBrush}"/><Window.Resources>
  38.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  39. </Window.Resources>
  40. <Button Background="{StaticResource RedBrush}"/>DependencyProperty.RegisterAttached("Freeze", typeof(bool), typeof(PresentationOptionsAttach), new PropertyMetadata(false, OnFreezeChanged));<Window.Resources>
  41.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  42. </Window.Resources>
  43. <Button Background="{StaticResource RedBrush}"/>private static void OnFreezeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)<Window.Resources>
  44.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  45. </Window.Resources>
  46. <Button Background="{StaticResource RedBrush}"/>{<Window.Resources>
  47.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  48. </Window.Resources>
  49. <Button Background="{StaticResource RedBrush}"/><Window.Resources>
  50.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  51. </Window.Resources>
  52. <Button Background="{StaticResource RedBrush}"/>if (DesignerProperties.GetIsInDesignMode(d)) return;<Window.Resources>
  53.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  54. </Window.Resources>
  55. <Button Background="{StaticResource RedBrush}"/><Window.Resources>
  56.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  57. </Window.Resources>
  58. <Button Background="{StaticResource RedBrush}"/>if ((bool)e.NewValue)<Window.Resources>
  59.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  60. </Window.Resources>
  61. <Button Background="{StaticResource RedBrush}"/><Window.Resources>
  62.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  63. </Window.Resources>
  64. <Button Background="{StaticResource RedBrush}"/>{<Window.Resources>
  65.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  66. </Window.Resources>
  67. <Button Background="{StaticResource RedBrush}"/><Window.Resources>
  68.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  69. </Window.Resources>
  70. <Button Background="{StaticResource RedBrush}"/><Window.Resources>
  71.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  72. </Window.Resources>
  73. <Button Background="{StaticResource RedBrush}"/>Freezable freezable = d as Freezable;<Window.Resources>
  74.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  75. </Window.Resources>
  76. <Button Background="{StaticResource RedBrush}"/><Window.Resources>
  77.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  78. </Window.Resources>
  79. <Button Background="{StaticResource RedBrush}"/><Window.Resources>
  80.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  81. </Window.Resources>
  82. <Button Background="{StaticResource RedBrush}"/>if (freezable.CanFreeze)<Window.Resources>
  83.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  84. </Window.Resources>
  85. <Button Background="{StaticResource RedBrush}"/><Window.Resources>
  86.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  87. </Window.Resources>
  88. <Button Background="{StaticResource RedBrush}"/><Window.Resources>
  89.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  90. </Window.Resources>
  91. <Button Background="{StaticResource RedBrush}"/><Window.Resources>
  92.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  93. </Window.Resources>
  94. <Button Background="{StaticResource RedBrush}"/>freezable.Freeze();<Window.Resources>
  95.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  96. </Window.Resources>
  97. <Button Background="{StaticResource RedBrush}"/><Window.Resources>
  98.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  99. </Window.Resources>
  100. <Button Background="{StaticResource RedBrush}"/>}<Window.Resources>
  101.     <SolidColorBrush x:Key="RedBrush" Color="Red"/>
  102. </Window.Resources>
  103. <Button Background="{StaticResource RedBrush}"/>}}
复制代码
小结

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

来源:https://www.cnblogs.com/czwy/archive/2023/10/18/17773084.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具