WPF性能优化:Freezable 对象
Freezable是WPF中一個特殊的基類,用于創建可以凍結(Freeze)的可變對象。凍結一個對象意味著將其狀態設置為只讀,從而提高性能并允許在多線程環境中共享對象。
Freezable的應用
我們定義畫刷資源的時候常常會這樣寫:
<SolidColorBrush x:Key="RedBrush" Color="Red" o:Freeze="True"/>
代碼中的o:Freeze="True"其實就是使用Freezable的 Freeze方法凍結畫刷,使之不可修改,系統不必監視該畫刷對象,從而減少資源消耗。
o:Freeze="True"乍一看像附加屬性,其實并不是的。Freeze屬性是http://schemas.microsoft.com/winfx/2006/xaml/presentation/optionsXML命名空間中定義的唯一屬性或其他編程元素。Freeze屬性專門存在于此特殊命名空間中,以便在根元素聲明中可以使用。處理Freeze屬性的功能專門內置于處理已編譯應用程序的 XAML的XAML處理器中。
那是不是WPF中的所有資源都可以(需要)使用Freeze方法凍結來提高性能呢?
Freezable類通常用于WPF中的資源和動畫,例如創建可重用的畫刷、幾何圖形和動畫。從Freezable繼承的類型包括Brush、Transform和Geometry類。由于它們包含非托管資源,因此系統必須監視這些對象發生的修改,然后在原始對象發生更改時更新對應的非托管資源。即使實際上并未修改圖形系統對象,系統仍必須消耗一些資源來監視該對象,以防更改它。
例如,假設創建一個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。但是,可以使用Clone或CloneCurrentValue方法創建(深拷貝)解凍的副本。如果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 对象的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SQL Server中获取不同格式的日期
- 下一篇: 2023-08-06:小青蛙住在一条河边