Средства синхронизации потоковПри использовании многопоточности естественным образом возникает проблема синхронизации потоков, то есть координации их действий для получения предсказуемого результата. Чтобы сделать код потокобезопасным, необходимо гарантировать выполнение операторов, составляющих тело метода, только одним потоком в любой момент времени. Такие блоки кода называются критическими секциями. Для организации критических секций платформа .NET предлагает статический класс System.Threading.Monitor. Метод Monitor.Enter() определяет вход в критическую секцию, а метод Monitor.Exit() – выход из секции. Вход и выход должны выполняться в одном и том же потоке.
Класс System.Threading.Mutex (мьютекс) подобен классу Monitor, но позволяет организовать критическую секцию для нескольких процессов. Применяя Mutex, нужно вызвать метод WaitOne() для входа в критическую секцию, а метод ReleaseMutex() – для выхода из неё. Типичный пример использования мьютекса – создание приложения, которое можно запустить только в одном экземпляре.
Семафор – это объект синхронизации, позволяющий войти в заданный участок кода не более чем N потокам (N – ёмкость семафора). Аналогией семафора является охранник у входа в клуб с фиксированным количеством мест. Новые посетители попадают в заполненный клуб, только если из него кто-то ушёл. Се- мафор с ёмкостью, равной единице, аналогичен монитору или мьютексу, однако получение и снятие блокировки в случае семафора может выполняться из разных потоков. Для организации есть классы Semaphore и SemaphoreSlim из пространства имён System.Threading. Первый класс применяется для синхронизации между процессами, второй работает только в рамках одного процесса. Метод Wait() этих классов выполняет получение блокировки, а метод Release() – снятие блокировки.
Стили и шаблоны в WPFСтиль – это коллекция значений свойств, которые могут быть применены к элементу. В WPF стили играют ту же роль, которую CSS играет в HTML-разметке. Подобно CSS, стили WPF позволяют определять общий набор характеристик форматирования и применять их по всему приложению для обеспечения согласованности. Стили могут работать автоматически, предназначаться для элементов конкретного типа и каскадироваться через дерево элементов. Рассмотрение стилей начнём с конкретного примера, в котором определяется и применяется стиль для кнопок.
<StackPanel Orientation="Horizontal" Margin="30">
<StackPanel.Resources>
<Style x:Key="buttonStyle">
<Setter Property="Button.FontSize" Value="22" />
<Setter Property="Button.Background" Value="Purple" />
</Style>
</StackPanel.Resources>
<Button Style="{StaticResource buttonStyle}">1</Button>
</StackPanel>
Любой стиль в WPF – это объект класса System.Windows.Style. Основным свойством стиля является коллекция Setters (свойство содержимого), в которой каждый элемент задаёт значение для некоторого свойства зависимостей (стили работают только со свойствами зависимостей). Чтобы задать значение для свойства зависимостей, нужно указать имя этого свойства. В нашем примере имя включает префикс – класс элемента. Если требуется применить один стиль к визуальным элементам разных типов, для префикса используется имя общего типа-предка:
<Style x:Key="controlStyle">
Определяя стиль, можно построить его на основе стиля-предка. Для этого следует воспользоваться свойством стиля BasedOn. Стили также могут содержать локальные логические ресурсы (коллекция Resources):
BasedOn="{StaticResource baseStyle}
Рассмотрим применение триггеров при описании стиля. У триггера настраиваются: имя свойства, с которым связан триггер; значение свойства, которое задаёт условие старта триггера; коллекция Setters, описывающая действие триггера. перемещении над кнопкой указателя мыши происходил поворот кнопки:
<Style x:Key="buttonStyle" TargetType="Button">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Black" />
<Setter Property="RenderTransform">
<Setter.Value>
<RotateTransform Angle="10" />
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
Шаблоны – фундаментальная концепция технологии WPF. Шаблоны обеспечивают настраиваемое представление (внешний вид) для элементов управления и произвольных объектов, отображаемых как содержимое элементов. Большинство элементов управления имеют внешний вид и поведение. Рассмотрим кнопку: внешним видом является область для нажатия, а поведением – событие Click. WPF разделяет внешний вид и поведение, благодаря концепции шаблона элемента управления. Шаблон элемента управления – это экземпляр класса System.Windows.ControlTemplate. Основным свойством шаблона является свойство содержимого VisualTree, которое содержит визуальный элемент, определяющий внешний вид шаблона. В элементах управления ссылка на шаблон устанавливается через свойство Template.(примеры в методе)
<Button Content="Sample" Width="120" Height="80" Padding="15">
<Button.Template>
<ControlTemplate>
<Border BorderBrush="Blue" BorderThickness="4"
CornerRadius="2" Background="Gold" />
</ControlTemplate>
</Button.Template>
</Button>
Шаблон данных – механизм для настройки отображения объектов заданного типа. Любой шаблон данных – это объект System.Windows.DataTemplate. Основное свойство шаблона данных – VisualTree. Оно содержит визуальный элемент, определяющий внешний вид шаблона. При формировании VisualTree обычно используется привязка данных для извлечения информации из объекта, для которого применяется шаблон. Сам шаблон данных, как правило, размещают в ресурсах окна или приложения.