Общие сведения об объектах класса FreezableFreezable Objects Overview

В этом разделе описывается эффективное использование и создание объектов Freezable, которые предоставляют специальные функции, которые могут помочь повысить производительность приложения.This topic describes how to effectively use and create Freezable objects, which provide special features that can help improve application performance. Примерами объектов Freezable являются кисти, перья, преобразования, геометрические объекты и анимация.Examples of freezable objects include brushes, pens, transformations, geometries, and animations.

Что такое Freezable?What Is a Freezable?

Freezable — это особый тип объекта с двумя состояниями: незамороженный и замороженный.A Freezable is a special type of object that has two states: unfrozen and frozen. Если не заморозить, то поведение Freezable выглядит как любой другой объект.When unfrozen, a Freezable appears to behave like any other object. После заморозки Freezable больше не может быть изменена.When frozen, a Freezable can no longer be modified.

Freezable предоставляет событие Changed для уведомления наблюдателей о любых изменениях в объекте.A Freezable provides a Changed event to notify observers of any modifications to the object. Замораживание Freezable может повысить его производительность, так как больше не требуется тратить ресурсы на уведомления об изменениях.Freezing a Freezable can improve its performance, because it no longer needs to spend resources on change notifications. Замороженные Freezable также можно совместно использовать в потоках, в то время как незамороженный Freezable не может.A frozen Freezable can also be shared across threads, while an unfrozen Freezable cannot.

Несмотря на то, что класс Freezable содержит много приложений, большинство Freezable объектов в Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) связаны с графической подсистемой.Although the Freezable class has many applications, most Freezable objects in Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) are related to the graphics sub-system.

Класс Freezable упрощает использование определенных объектов графической системы и помогает повысить производительность приложений.The Freezable class makes it easier to use certain graphics system objects and can help improve application performance. Примерами типов, которые наследуют от Freezable, являются классы Brush, Transformи Geometry.Examples of types that inherit from Freezable include the Brush, Transform, and Geometry classes. Поскольку они содержат неуправляемые ресурсы, система должна отслеживать эти объекты для внесения изменений, а затем обновлять соответствующие неуправляемые ресурсы при изменении исходного объекта.Because they contain unmanaged resources, the system must monitor these objects for modifications, and then update their corresponding unmanaged resources when there is a change to the original object. Даже если вы не изменяете объект графической системы, система должна по-прежнему тратить некоторые ресурсы на наблюдение за объектом, если вы его изменяете.Even if you don't actually modify a graphics system object, the system must still spend some of its resources monitoring the object, in case you do change it.

Например, предположим, что вы создаете кисть SolidColorBrush и используете ее для рисования фона кнопки.For example, suppose you create a SolidColorBrush brush and use it to paint the background of a button.

Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);
myButton.Background = myBrush;  
Dim myButton As New Button()
Dim myBrush As New SolidColorBrush(Colors.Yellow)
myButton.Background = myBrush

При отображении кнопки WPFWPF графическая подсистема использует предоставленные сведения для рисования группы пикселей, чтобы создать внешний вид кнопки.When the button is rendered, the WPFWPF graphics sub-system uses the information you provided to paint a group of pixels to create the appearance of a button. Несмотря на то, что для описания того, как должна быть окрашена кнопка, используется сплошная Цветная кисть, сплошная цветовая кисть не выполняет рисование.Although you used a solid color brush to describe how the button should be painted, your solid color brush doesn't actually do the painting. Графическая система создает быстрые низкоуровневые объекты для кнопки и кисти, и это объекты, которые фактически отображаются на экране.The graphics system generates fast, low-level objects for the button and the brush, and it is those objects that actually appear on the screen.

Если вы изменили кисть, эти низкоуровневые объекты пришлось бы повторно создать.If you were to modify the brush, those low-level objects would have to be regenerated. Класс Freezable дает кисти возможность находить соответствующие созданные объекты низкого уровня и обновлять их при изменении.The freezable class is what gives a brush the ability to find its corresponding generated, low-level objects and to update them when it changes. Если эта возможность включена, кисть называется «незамороженной».When this ability is enabled, the brush is said to be "unfrozen."

Метод Freeze Freezable позволяет отключить эту возможность самостоятельного обновления.A freezable's Freeze method enables you to disable this self-updating ability. Этот метод можно использовать, чтобы сделать кисть замороженной или неизменяемой.You can use this method to make the brush become "frozen," or unmodifiable.

Примечание

Не каждый объект Freezable может быть заморожен.Not every Freezable object can be frozen. Чтобы избежать возникновения InvalidOperationException, проверьте значение свойства CanFreeze объекта Freezable, чтобы определить, можно ли его заморозить перед попыткой его заморозить.To avoid throwing an InvalidOperationException, check the value of the Freezable object's CanFreeze property to determine whether it can be frozen before attempting to freeze it.

if (myBrush.CanFreeze)
{
    // Makes the brush unmodifiable.
    myBrush.Freeze();
}
If myBrush.CanFreeze Then
    ' Makes the brush unmodifiable.
    myBrush.Freeze()
End If

Если вам больше не нужно изменять Freezable, замораживание обеспечивает преимущества производительности.When you no longer need to modify a freezable, freezing it provides performance benefits. Если вы захотите заморозить кисть в этом примере, графической системе больше не потребуется отслеживать изменения.If you were to freeze the brush in this example, the graphics system would no longer need to monitor it for changes. Графическая система также может выполнять другие оптимизации, так как она знает, что кисть не изменится.The graphics system can also make other optimizations, because it knows the brush won't change.

Примечание

Для удобства объекты Freezable остаются незафиксированными, если их явно не заморозить.For convenience, freezable objects remain unfrozen unless you explicitly freeze them.

Использование FreezableUsing Freezables

Использование незамороженного объекта Freezable аналогично использованию любого другого типа объектов.Using an unfrozen freezable is like using any other type of object. В следующем примере цвет SolidColorBrush меняется с желтого на красный после того, как он используется для рисования фона кнопки.In the following example, the color of a SolidColorBrush is changed from yellow to red after it's used to paint the background of a button. Графическая система работает в фоновом режиме для автоматического изменения кнопки с желтого на красную при следующем обновлении экрана.The graphics system works behind the scenes to automatically change the button from yellow to red the next time the screen is refreshed.

Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);
myButton.Background = myBrush;  


// Changes the button's background to red.
myBrush.Color = Colors.Red;
Dim myButton As New Button()
Dim myBrush As New SolidColorBrush(Colors.Yellow)
myButton.Background = myBrush


' Changes the button's background to red.
myBrush.Color = Colors.Red

Замораживание FreezableFreezing a Freezable

Чтобы сделать Freezable неизменяемым, вызовите его метод Freeze.To make a Freezable unmodifiable, you call its Freeze method. При замораживании объекта, содержащего объекты Freezable, эти объекты также фиксируются.When you freeze an object that contains freezable objects, those objects are frozen as well. Например, если заморозить PathGeometry, содержащиеся в нем данные и сегменты будут зафиксированы.For example, if you freeze a PathGeometry, the figures and segments it contains would be frozen too.

Freezable нельзя зафиксировать, если выполняется одно из следующих условий.A Freezable can't be frozen if any of the following are true:

  • Он имеет анимированные или привязанные к данным свойства.It has animated or data bound properties.

  • Он имеет свойства, заданные динамическим ресурсом.It has properties set by a dynamic resource. (Дополнительные сведения о динамических ресурсах см. в разделе ресурсы XAML .)(See the XAML Resources for more information about dynamic resources.)

  • Он содержит Freezable подобъекты, которые не могут быть заморожены.It contains Freezable sub-objects that can't be frozen.

Если эти условия имеют значение false и вы не собираетесь изменять Freezable, следует закрепить его, чтобы получить выигрыш в производительности, описанный выше.If these conditions are false, and you don't intend to modify the Freezable, then you should freeze it to gain the performance benefits described earlier.

После вызова метода Freeze Freezable его нельзя изменить.Once you call a freezable's Freeze method, it can no longer be modified. Попытка изменить зафиксированный объект приводит к возникновению InvalidOperationException.Attempting to modify a frozen object causes an InvalidOperationException to be thrown. Следующий код вызывает исключение, так как пытается изменить кисть после ее замораживания.The following code throws an exception, because we attempt to modify the brush after it's been frozen.


Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);          

if (myBrush.CanFreeze)
{
    // Makes the brush unmodifiable.
    myBrush.Freeze();
}

myButton.Background = myBrush;  

try {

    // Throws an InvalidOperationException, because the brush is frozen.
    myBrush.Color = Colors.Red;
}catch(InvalidOperationException ex)
{
    MessageBox.Show("Invalid operation: " + ex.ToString());
}


Dim myButton As New Button()
Dim myBrush As New SolidColorBrush(Colors.Yellow)

If myBrush.CanFreeze Then
    ' Makes the brush unmodifiable.
    myBrush.Freeze()
End If

myButton.Background = myBrush

Try

    ' Throws an InvalidOperationException, because the brush is frozen.
    myBrush.Color = Colors.Red
Catch ex As InvalidOperationException
    MessageBox.Show("Invalid operation: " & ex.ToString())
End Try

Чтобы избежать возникновения этого исключения, можно использовать метод IsFrozen, чтобы определить, заморожен ли Freezable.To avoid throwing this exception, you can use the IsFrozen method to determine whether a Freezable is frozen.


Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);

if (myBrush.CanFreeze)
{
    // Makes the brush unmodifiable.
    myBrush.Freeze();
}            

myButton.Background = myBrush;


if (myBrush.IsFrozen) // Evaluates to true.
{
    // If the brush is frozen, create a clone and
    // modify the clone.
    SolidColorBrush myBrushClone = myBrush.Clone();
    myBrushClone.Color = Colors.Red;
    myButton.Background = myBrushClone;
}
else
{
    // If the brush is not frozen,
    // it can be modified directly.
    myBrush.Color = Colors.Red;
}



Dim myButton As New Button()
Dim myBrush As New SolidColorBrush(Colors.Yellow)

If myBrush.CanFreeze Then
    ' Makes the brush unmodifiable.
    myBrush.Freeze()
End If

myButton.Background = myBrush


If myBrush.IsFrozen Then ' Evaluates to true.
    ' If the brush is frozen, create a clone and
    ' modify the clone.
    Dim myBrushClone As SolidColorBrush = myBrush.Clone()
    myBrushClone.Color = Colors.Red
    myButton.Background = myBrushClone
Else
    ' If the brush is not frozen,
    ' it can be modified directly.
    myBrush.Color = Colors.Red
End If


В предыдущем примере кода была сделана изменяемая копия зафиксированного объекта с помощью метода Clone.In the preceding code example, a modifiable copy was made of a frozen object using the Clone method. В следующем разделе приводятся более подробные сведения о клонировании.The next section discusses cloning in more detail.

Примечание

Поскольку зафиксированное Freezable не может быть анимированным, система анимации автоматически создает изменяемые клоны зафиксированных Freezable объектов при попытке анимировать их с помощью Storyboard.Because a frozen freezable cannot be animated, the animation system will automatically create modifiable clones of frozen Freezable objects when you try to animate them with a Storyboard. Чтобы устранить издержки производительности, вызванные клонированием, оставьте объект незамороженным, если вы планируете его анимировать.To eliminate the performance overhead caused by cloning, leave an object unfrozen if you intend to animate it. Дополнительные сведения об анимации с помощью раскадровок см. в разделе Общие сведения о раскадровках.For more information about animating with storyboards, see the Storyboards Overview.

Замораживание из разметкиFreezing from Markup

Для закрепления объекта Freezable, объявленного в разметке, используется атрибут PresentationOptions:Freeze.To freeze a Freezable object declared in markup, you use the PresentationOptions:Freeze attribute. В следующем примере SolidColorBrush объявляется как ресурс страницы и зафиксирован.In the following example, a SolidColorBrush is declared as a page resource and frozen. Затем он используется для задания фона кнопки.It is then used to set the background of a button.

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" 
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  mc:Ignorable="PresentationOptions">

  <Page.Resources>

    <!-- This resource is frozen. -->
    <SolidColorBrush 
      x:Key="MyBrush"
      PresentationOptions:Freeze="True" 
      Color="Red" />
  </Page.Resources>


  <StackPanel>

    <Button Content="A Button" 
      Background="{StaticResource MyBrush}">
    </Button>

  </StackPanel>
</Page>

Чтобы использовать атрибут Freeze, необходимо выполнить преобразование в пространство имен "Параметры представления": http://schemas.microsoft.com/winfx/2006/xaml/presentation/options.To use the Freeze attribute, you must map to the presentation options namespace: http://schemas.microsoft.com/winfx/2006/xaml/presentation/options. PresentationOptions является рекомендуемым префиксом для сопоставления этого пространства имен:PresentationOptions is the recommended prefix for mapping this namespace:

xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"

Так как не все читатели XAML распознают этот атрибут, рекомендуется использовать атрибут MC: Ignorable , чтобы пометить атрибут Presentation:Freeze как игнорируемый:Because not all XAML readers recognize this attribute, it's recommended that you use the mc:Ignorable Attribute to mark the Presentation:Freeze attribute as ignorable:

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions"

Дополнительные сведения см. на странице MC: Ignorable Attribute .For more information, see the mc:Ignorable Attribute page.

"Unfreezingе" Freezable"Unfreezing" a Freezable

После замораживания Freezable не может быть изменена или незаморожена. Однако можно создать незамороженный клон с помощью метода Clone или CloneCurrentValue.Once frozen, a Freezable can never be modified or unfrozen; however, you can create an unfrozen clone using the Clone or CloneCurrentValue method.

В следующем примере фон кнопки задается кистью, а кисть заморожена.In the following example, the button's background is set with a brush and that brush is then frozen. При помощи метода Clone выполняется незамороженная копия кисти.An unfrozen copy is made of the brush using the Clone method. Клон изменяется и используется для изменения фона кнопки с желтого на красный.The clone is modified and used to change the button's background from yellow to red.

Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);

// Freezing a Freezable before it provides
// performance improvements if you don't
// intend on modifying it. 
if (myBrush.CanFreeze)
{
    // Makes the brush unmodifiable.
    myBrush.Freeze();
}
            

myButton.Background = myBrush;  

// If you need to modify a frozen brush,
// the Clone method can be used to
// create a modifiable copy.
SolidColorBrush myBrushClone = myBrush.Clone();

// Changing myBrushClone does not change
// the color of myButton, because its
// background is still set by myBrush.
myBrushClone.Color = Colors.Red;

// Replacing myBrush with myBrushClone
// makes the button change to red.
myButton.Background = myBrushClone;
Dim myButton As New Button()
Dim myBrush As New SolidColorBrush(Colors.Yellow)

' Freezing a Freezable before it provides
' performance improvements if you don't
' intend on modifying it. 
If myBrush.CanFreeze Then
    ' Makes the brush unmodifiable.
    myBrush.Freeze()
End If


myButton.Background = myBrush

' If you need to modify a frozen brush,
' the Clone method can be used to
' create a modifiable copy.
Dim myBrushClone As SolidColorBrush = myBrush.Clone()

' Changing myBrushClone does not change
' the color of myButton, because its
' background is still set by myBrush.
myBrushClone.Color = Colors.Red

' Replacing myBrush with myBrushClone
' makes the button change to red.
myButton.Background = myBrushClone

Примечание

Независимо от того, какой метод клонирования вы используете, анимации никогда не копируются в новый Freezable.Regardless of which clone method you use, animations are never copied to the new Freezable.

Методы Clone и CloneCurrentValue создают глубокие копии объекта Freezable.The Clone and CloneCurrentValue methods produce deep copies of the freezable. Если объект Freezable содержит другие замороженные объекты Freezable, они также копируются и становятся изменяемыми.If the freezable contains other frozen freezable objects, they are also cloned and made modifiable. Например, при клонировании зафиксированной PathGeometry, чтобы сделать его изменяемым, содержащиеся в нем данные и рисунки также копируются и становятся изменяемыми.For example, if you clone a frozen PathGeometry to make it modifiable, the figures and segments it contains are also copied and made modifiable.

Создание собственного класса FreezableCreating Your Own Freezable Class

Класс, производный от Freezable, получает следующие функции.A class that derives from Freezable gains the following features.

  • Особые состояния: доступное только для чтения (зафиксированное) и состояние с возможностью записи.Special states: a read-only (frozen) and a writable state.

  • Потокобезопасность. замороженная Freezable может совместно использоваться несколькими потоками.Thread safety: a frozen Freezable can be shared across threads.

  • Подробное уведомление об изменении. в отличие от других DependencyObject, объекты Freezable предоставляют уведомления об изменениях при изменении значений подсвойств.Detailed change notification: Unlike other DependencyObjects, Freezable objects provide change notifications when sub-property values change.

  • Простое клонирование: класс Freezable уже реализовал несколько методов, создающих глубокие клоны.Easy cloning: the Freezable class has already implemented several methods that produce deep clones.

Freezable является типом DependencyObjectи, следовательно, использует систему свойств зависимостей.A Freezable is a type of DependencyObject, and therefore uses the dependency property system. Свойства класса не обязательно должны быть свойствами зависимостей, но использование свойств зависимости уменьшит объем кода, который необходимо написать, так как класс Freezable был разработан с учетом свойств зависимостей.Your class properties don't have to be dependency properties, but using dependency properties will reduce the amount of code you have to write, because the Freezable class was designed with dependency properties in mind. Дополнительные сведения о системе свойств зависимостей см. в разделе Общие сведения о свойствах зависимостей.For more information about the dependency property system, see the Dependency Properties Overview.

Каждый подкласс Freezable должен переопределять метод CreateInstanceCore.Every Freezable subclass must override the CreateInstanceCore method. Если ваш класс использует свойства зависимостей для всех своих данных, то все готово.If your class uses dependency properties for all its data, you're finished.

Если класс содержит элементы данных, не относящиеся к свойствам зависимостей, необходимо также переопределить следующие методы.If your class contains non-dependency property data members, you must also override the following methods:

Также необходимо соблюдать следующие правила доступа к элементам данных и их записи, которые не являются свойствами зависимостей.You must also observe the following rules for accessing and writing to data members that are not dependency properties:

  • В начале любого API, считывающего члены данных, не относящиеся к свойствам зависимостей, вызовите метод ReadPreamble.At the beginning of any API that reads non-dependency property data members, call the ReadPreamble method.

  • В начале любого API, который записывает члены данных, не относящиеся к свойствам зависимостей, вызовите метод WritePreamble.At the beginning of any API that writes non-dependency property data members, call the WritePreamble method. (После вызова WritePreamble в API-интерфейсе не нужно выполнять дополнительный вызов ReadPreamble, если также считываются члены данных, не являющиеся свойствами зависимостей.)(Once you've called WritePreamble in an API, you don't need to make an additional call to ReadPreamble if you also read non-dependency property data members.)

  • Вызовите метод WritePostscript перед выходом методов, которые выполняют запись в члены данных свойств, не являющихся зависимостями.Call the WritePostscript method before exiting methods that write to non-dependency property data members.

Если класс содержит элементы данных, не являющиеся свойствами зависимости, которые являются DependencyObject объектами, необходимо также вызвать метод OnFreezablePropertyChanged при каждом изменении одного из значений, даже если вы настраиваете элемент на null.If your class contains non-dependency-property data members that are DependencyObject objects, you must also call the OnFreezablePropertyChanged method each time you change one of their values, even if you're setting the member to null.

Примечание

Очень важно начинать каждый Freezable метод, переопределяемый с помощью вызова базовой реализации.It's very important that you begin each Freezable method you override with a call to the base implementation.

Пример настраиваемого класса Freezable см. в разделе Пример пользовательской анимации.For an example of a custom Freezable class, see the Custom Animation Sample.

См. такжеSee also