Общие сведения об объектах класса Freezable
В этом разделе описывается, как эффективно использовать и создавать Freezable объекты, которые предоставляют специальные функции, которые могут помочь повысить производительность приложения. Объекты freezable примеры кисти, перья, преобразования, геометрии и анимации.
Что такое Freezable?
Объект Freezable — это специальный тип объекта, имеющий два состояния: фиксированное и нефиксированное. Незафиксированный Freezable ведет себя как любой другой объект. Зафиксированный Freezable не может быть изменен.
Объект Freezable предоставляет Changed событие, чтобы уведомлять наблюдателей об каких-либо изменений объекта. Замораживание Freezable позволяет повысить его производительность, поскольку он больше не требуется тратить ресурсы на уведомления об изменениях. Зафиксированный Freezable также может использоваться несколькими потоками, в отличие от незафиксированных Freezable невозможно.
Несмотря на то что Freezable класс имеет много приложений, наиболее Freezable объекты в Windows Presentation Foundation (WPF) связаны с графическая подсистема.
Freezable Класс упрощает использование определенных объектов графических систем и может повысить производительность приложения. Примеры типов, которые наследуют от Freezable включают Brush, Transform, и Geometry классы. Так как они содержат неуправляемые ресурсы, система должна отслеживать изменения этих объектов и затем обновить соответствующие им неуправляемые ресурсы, при наличии изменений в исходный объект. Даже если вы не меняете фактически объект графической системы, системы необходимо по-прежнему тратить часть его ресурсов, наблюдение за объектом, в случае, если изменить его.
Предположим, например, можно создать SolidColorBrush кисти и использовать его для рисования фона кнопки.
Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);
myButton.Background = myBrush;
При отображении кнопки WPF графическая подсистема использует сведения, предоставленные для закраски группы пикселей, которое необходимо создать внешний вид кнопки. Несмотря на то, что вы использовали Одноцветная кисть для описания того, как должен быть окрашен кнопки, сплошной цвет кисти фактически не выполняет заливку. Графическая система создает быстрые низкоуровневые объекты для кнопки и кисти, а это те объекты, которые отображаются на экране.
При изменении кисти, эти низкоуровневые объекты бы быть создан повторно. Класс freezable представляет, что дает возможность найти соответствующие объекты низкоуровневые и обновлять их при его изменении кисти. Если эта возможность включена, кисть, которая называется «незафиксированной».
Freezable Freeze метод позволяет отключить данную возможность самостоятельного обновления. Этот метод можно использовать, чтобы сделать кисть «зафиксированной» или неизменяемым.
Note
Не каждый объект Freezable может быть зафиксирован. Чтобы избежать возникновения InvalidOperationException, проверьте значение свойства объекта Freezable CanFreeze свойства, чтобы определить, является ли он быть зафиксирован перед фиксированием.
if (myBrush.CanFreeze)
{
// Makes the brush unmodifiable.
myBrush.Freeze();
}
Если вам больше не нужно изменять freezable, зафиксировать этот дает выигрыш в производительности. Если закрепить кисть, которая в этом примере, графическая система больше не потребуется отслеживать его изменения. Графическая система также может отправлять другие виды оптимизации, поскольку известно, что кисть, которая не изменится.
Note
Для удобства объекты freezable остаются незафиксированными, пока вы явным образом замораживайте.
С помощью объектов Freezable
Использование незафиксированного freezable аналогично использованию любого другого типа объекта. В следующем примере цвет SolidColorBrush изменяется с желтого на красный после он используется для рисования фона кнопки. Графическая система работает незаметно для автоматического изменения кнопки с желтого на красный при очередном обновлении экрана.
Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);
myButton.Background = myBrush;
// Changes the button's background to red.
myBrush.Color = Colors.Red;
Замораживание Freezable
Чтобы сделать Freezable неизменяемым, необходимо вызвать его Freeze метод. Когда вы закрепить объект, содержащий объекты freezable, эти объекты также закрепляются. Например, если зафиксировать PathGeometry, рисунки и сегменты будут зафиксированы.
Freezable нельзя зафиксировать, если одно из следующих условий:
Объект имеет анимированные или свойства с привязкой к данным.
Он имеет свойства, заданные на динамический ресурс. (См. в разделе ресурсы XAML Дополнительные сведения о динамических ресурсов.)
Он содержит Freezable вложенные объекты, которые нельзя зафиксировать.
Если эти условия имеют значение false, и вы не собираетесь изменять Freezable, то стоит зафиксировать, чтобы получить выигрыш в производительности, описанные ранее.
При вызове метода freezable Freeze метод, он не может быть изменен. Попытка изменить зафиксированного объекта возникает InvalidOperationException исключение. Следующий код создает исключение, так как выполняется попытка изменить кисть после она была зафиксирована.
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());
}
Чтобы избежать возникновения этого исключения, можно использовать IsFrozen метод, чтобы определить, является ли Freezable заморожен.
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;
}
В предыдущем примере кода, изменяемая копия была сделана зафиксированного объекта с помощью Clone метод. В следующем разделе рассматривается более подробно клонирования.
Примечание поскольку зафиксированного freezable невозожно анимировать, системы анимации автоматически создаст изменяемые клоны замороженный Freezable объектов при попытке их с помощью анимации Storyboard. Чтобы снизить издержки из-за клонирования, оставьте объект незафиксированным, если вы собираетесь анимировать его. Дополнительные сведения об анимации с помощью раскадровки см. в разделе Общие сведения о раскадровках.
Замораживание из разметки
Чтобы закрепить Freezable объявленный в разметке, можно использовать PresentationOptions:Freeze
атрибута. В следующем примере SolidColorBrush объявляется как ресурс страницы и зафиксирован. Затем используется для установки фона кнопки.
<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
. PresentationOptions
— Это рекомендуемый префикс для сопоставления данного пространства имен:
xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
Так как не все средства чтения XAML распознают этот атрибут, рекомендуется использовать mc: Ignorable-атрибут для пометки Presentation:Freeze
атрибут ignorable как:
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions"
Дополнительные сведения см. в разделе mc: Ignorable-атрибут страницы.
«Размораживание» Freezable
После фиксации Freezable никогда не может быть изменен или разморозить; тем не менее, можно создать с помощью незафиксированную копию Clone или CloneCurrentValue метод.
В следующем примере фона кнопки задается с помощью кисти и кисти, затем заморожен. Незафиксированная копия состоит из кисти с использованием Clone метод. Клон изменяется и используется для изменения фона кнопки с желтого на красный.
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;
Note
Независимо от используемого метода клонирования, анимация никогда не копируется в новый Freezable.
Clone И CloneCurrentValue методы создают детальные копии объекта freezable. Если объект freezable содержит другие зафиксированные объекты freezable, они также клонируются и становятся изменяемыми. Например, если копировать зафиксированный PathGeometry чтобы сделать его изменяемым, рисунки и сегменты также копируются и становятся изменяемыми.
Создание собственного класса Freezable
Класс, производный от Freezable поддерживает следующие функции.
Особые состояния: только для чтения (замороженным) и состояние для записи.
Потокобезопасность: зафиксированный Freezable может использоваться несколькими потоками.
Подробные уведомления об изменениях: В отличие от других DependencyObjects, объектах класса Freezable предоставить уведомление об изменениях, при изменении значений вложенных свойств.
Удобное клонирование: Freezable класс уже реализовал несколько методов, которые обеспечивают большую глубину клонирования.
Объект Freezable — это разновидность DependencyObjectи поэтому использует в системе свойств зависимостей. Свойства класса не обязательно должны быть свойствами зависимости, но использование свойств зависимостей уменьшит объем кода, необходимо написать, так как Freezable класс был разработан с учетом свойств зависимости. Дополнительные сведения о системе свойств зависимостей, см. в разделе Общие сведения о свойствах зависимостей.
Каждый Freezable подкласс должен переопределять CreateInstanceCore метод. Если ваш класс использует свойства зависимости для всех своих данных, вы закончили.
Если класс содержит члены данных не свойство зависимости, необходимо также переопределить следующие методы:
Также необходимо соблюдать следующие правила для доступа и записи на данные-члены, которые не являются свойствами зависимостей:
В начале любого API , считывает элементы данных не свойство зависимости, вызовите ReadPreamble метод.
В начале любого API, который записывает элементы данных не свойство зависимости, вызовите WritePreamble метод. (После вызова WritePreamble в API, не требуется дополнительный вызов к ReadPreamble также считывать элементы данных не свойство зависимости.)
Вызовите WritePostscript метод перед выходом из методов, которые записывают на данные-члены не свойство зависимости.
Если класс содержит члены данных зависимостей свойства, которые являются DependencyObject объектов, необходимо также вызвать OnFreezablePropertyChanged метод каждый раз при изменении одного из их значения, даже если вы изменяете член null
.
Note
Очень важно, что началом реализации каждого Freezable метод можно переопределить с помощью вызова к базовой реализации.
Пример настраиваемого Freezable , представлена в разделе пример пользовательского.