在C# WPF的技术体系中,Freezable是一个位于System.Windows.Media.Animation命名空间下的抽象基类,它的设计初衷是为了优化依赖对象的状态管理和性能表现,很多WPF中的图形、动画、画笔等常用类型都直接或间接继承自Freezable。

Freezable的核心特性
Freezable最核心的特性是支持冻结状态,当一个Freezable对象被冻结后,它会进入只读状态,无法再修改其属性值,同时会释放部分内部开销,带来以下优势:
- 冻结后的对象可以被多个线程安全访问,不需要额外的线程同步操作
- 冻结后的对象会减少对依赖属性系统的开销,提升属性读取的性能
- 冻结后的对象可以被多个元素共享使用,不需要重复创建相同配置的对象实例
需要注意的是,只有当前对象的所有子对象都处于可冻结状态时,该Freezable对象才能被成功冻结,否则调用冻结方法会抛出异常。
Freezable的常用方法
1. 检查是否可冻结
可以通过CanFreeze属性判断当前Freezable对象是否可以被冻结,该属性返回布尔值,示例代码如下:
using System.Windows.Media; // 创建一个SolidColorBrush对象,它继承自Freezable SolidColorBrush brush = new SolidColorBrush(System.Windows.Media.Colors.Red); // 检查该对象是否可以被冻结 bool canFreeze = brush.CanFreeze;
2. 冻结对象
调用Freeze()方法可以将Freezable对象设置为冻结状态,该方法没有返回值,如果对象无法冻结会抛出InvalidOperationException异常,也可以使用Freeze(Freezable freezable)静态方法来冻结对象,示例代码如下:
using System.Windows.Media;
SolidColorBrush brush = new SolidColorBrush(System.Windows.Media.Colors.Blue);
// 判断是否可以冻结,再执行冻结操作避免异常
if (brush.CanFreeze)
{
// 实例方法冻结
brush.Freeze();
// 也可以使用静态方法冻结
// Freezable.Freeze(brush);
}
3. 创建可修改副本
如果需要在冻结后修改Freezable对象的属性,可以调用Clone()方法创建一个当前对象的可修改副本,副本默认处于未冻结状态,示例代码如下:
using System.Windows.Media; SolidColorBrush frozenBrush = new SolidColorBrush(System.Windows.Media.Colors.Green); frozenBrush.Freeze(); // 创建可修改的副本 SolidColorBrush clonedBrush = frozenBrush.Clone(); // 修改副本的属性 clonedBrush.Color = System.Windows.Media.Colors.Yellow;
4. 检查冻结状态
通过IsFrozen属性可以判断当前Freezable对象是否已经被冻结,返回true表示已冻结,不可修改,示例代码如下:
using System.Windows.Media; SolidColorBrush brush = new SolidColorBrush(System.Windows.Media.Colors.Red); bool isFrozenBefore = brush.IsFrozen; // 结果为false brush.Freeze(); bool isFrozenAfter = brush.IsFrozen; // 结果为true
Freezable的常见使用场景
场景1:共享画笔资源
在WPF中如果多个控件需要使用相同配置的画笔,直接创建多个实例会浪费资源,这时候可以创建一个Freezable的画笔对象并冻结,然后在多个控件中共享使用,示例代码如下:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
public class FreezableDemo
{
public static void CreateSharedBrush()
{
// 创建共享的画笔对象
SolidColorBrush sharedBrush = new SolidColorBrush(System.Windows.Media.Colors.Orange);
// 冻结画笔,使其可以被多个线程安全访问,同时提升性能
sharedBrush.Freeze();
// 创建两个按钮,共享同一个画笔
Button button1 = new Button();
button1.Content = "按钮1";
button1.Background = sharedBrush;
Button button2 = new Button();
button2.Content = "按钮2";
button2.Background = sharedBrush;
}
}
场景2:动画中的对象优化
在WPF动画中,如果使用的Freezable对象不需要在动画过程中修改,提前冻结可以减少动画运行时的开销,提升动画流畅度,示例代码如下:
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Animation;
public class AnimationDemo
{
public static void OptimizeAnimation()
{
// 创建旋转变换对象,继承自Freezable
RotateTransform rotateTransform = new RotateTransform();
// 冻结变换对象,动画中不需要修改该对象的基础配置
rotateTransform.Freeze();
// 创建动画
DoubleAnimation animation = new DoubleAnimation(0, 360, new Duration(TimeSpan.FromSeconds(2)));
animation.RepeatBehavior = RepeatBehavior.Forever;
// 将动画应用到冻结的变换对象上
rotateTransform.BeginAnimation(RotateTransform.AngleProperty, animation);
}
}
使用Freezable的注意事项
- 冻结操作是不可逆的,一旦对象被冻结,就无法再恢复到可修改状态,只能通过Clone方法创建新的可修改副本
- 如果Freezable对象包含未冻结的子对象,调用Freeze方法会失败,需要先处理所有子对象的冻结状态
- 冻结后的对象虽然不能被修改,但如果对象包含依赖属性,动画仍然可以修改这些依赖属性的值,这是WPF依赖属性的特殊机制
- 不是所有的Freezable对象都适合冻结,如果对象需要在后续频繁修改属性,冻结反而会增加创建副本的开销
Freezable是WPF中优化性能和资源管理的重要机制,合理运用冻结特性可以有效提升应用的运行效率,尤其是在处理大量图形、画笔、变换对象的场景中效果明显。
C#WPFFreezableFreezable_使用方法修改时间:2026-06-29 00:42:26