Оптимизация производительности: разметка и разработка

Разработка приложения WPF может повлиять на его производительность в результате создания ненужных служебных данных при вычислении макета и проверки ссылок на объекты. Конструирование объектов, особенно во время выполнения, может повлиять на характеристики производительности приложения.

В этом разделе содержатся рекомендации по производительности в этих областях.

Макет

Термин "проход разметки" описывает процесс измерения и упорядочения объекта Panel — коллекции дочерних объектов производного объекта, и затем рисование их на экране. Проход разметки представляет собой процесс интенсивной математической нагрузки — чем больше число дочерних объектов в коллекции, тем больше требуется вычислений. Например, при каждом изменении положения дочернего объекта UIElement в коллекции, он имеет возможность инициировать новую передачу системой разметки. Из-за разрыва отношения между характеристиками объекта и поведением разметки важно понимать тип событий, которые могут запустить систему разметки. Приложение будет выполняться лучше, если уменьшить, насколько возможно, ненужные вызовы прохода разметки.

Система разметки выполняет два прохода для каждого дочернего члена в коллекции: проход измерений и проход компоновки. Каждый дочерний объект предоставляет свою собственную переопределенную реализацию методов Measure и Arrange, чтобы обеспечить собственное поведение отдельной разметки. В самом простом случае макет является рекурсивной системой, в процессе которой программа изменяет размер и расположение элемента и отображает его на экране.

  • Дочерний объект UIElement начинает процесс разметки первым, задав его основные измеряемые свойства.

  • Вычисляются свойства объекта FrameworkElement, относящиеся к размеру, например Width, Height и Margin.

  • Применяется логика отдельного объекта Panel, например свойство Dock объекта DockPanel или свойство Orientation объекта StackPanel.

  • Содержимое компонуется или размещается после всех дочерних объектов, которые были измерены.

  • На экране отображается коллекция дочерних объектов.

Процесс прохода разметки вызывается снова при возникновении любого из следующих событий:

  • Дочерний объект добавляется к коллекции.

  • Свойство LayoutTransform применяется к дочернему объекту.

  • Метод UpdateLayout вызывается для дочернего объекта.

  • При изменении значения свойства зависимости, которое помечено метаданными, влияющими на проход измерения и компоновки.

Используйте наиболее эффективную панель там, где возможно

Сложность прохода разметки непосредственно основана на поведении разметки используемых элементов, производных объекта Panel. Например, объект Grid или элемент управления StackPanel предоставляет гораздо больше функциональных возможностей, чем элемент управления Canvas. Ценой этого значительного увеличения функциональности является увеличение затрат производительности. Однако если не требуются функциональные возможности, предоставляемые элементом управления Grid, следует использовать менее затратные варианты, например Canvas или настраиваемую панель.

Дополнительные сведения см. в разделе Общие сведения о панелях.

Обновление вместо замены RenderTransform

Можно обновить объект Transform вместо замены его в качестве значения свойства RenderTransform. Это особенно верно в скриптах, включающих анимацию. Обновление существующего объекта Transform позволяет избежать инициирования ненужных вычислений разметки.

Построение дерева сверху вниз

При добавлении или удалении узла из логического дерева свойство аннулирования вызывается на родительском узле и всех дочерних узлах. В результате, всегда требуется следовать шаблону структуры сверху вниз, во избежание ненужных аннулирований на узлах, которые уже были проверены. В следующей таблице показана разница в скорости выполнения между построением дерева сверху вниз или снизу вверх с глубиной 150 уровней с одним объектом TextBlock и DockPanel на каждом уровне.

Действие

Построение дерева (мс)

Отображение — включает построение дерева (мс)

Снизу вверх

366

454

Сверху вниз

11

96

В следующем примере кода демонстрируется создание дерева сверху вниз.

        Private Sub OnBuildTreeTopDown(ByVal sender As Object, ByVal e As RoutedEventArgs)
            Dim textBlock As New TextBlock()
            textBlock.Text = "Default"

            Dim parentPanel As New DockPanel()
            Dim childPanel As DockPanel

            myCanvas.Children.Add(parentPanel)
            myCanvas.Children.Add(textBlock)

            For i As Integer = 0 To 149
                textBlock = New TextBlock()
                textBlock.Text = "Default"
                parentPanel.Children.Add(textBlock)

                childPanel = New DockPanel()
                parentPanel.Children.Add(childPanel)
                parentPanel = childPanel
            Next i
        End Sub
private void OnBuildTreeTopDown(object sender, RoutedEventArgs e)
{
    TextBlock textBlock = new TextBlock();
    textBlock.Text = "Default";

    DockPanel parentPanel = new DockPanel();
    DockPanel childPanel;

    myCanvas.Children.Add(parentPanel);
    myCanvas.Children.Add(textBlock);

    for (int i = 0; i < 150; i++)
    {
        textBlock = new TextBlock();
        textBlock.Text = "Default";
        parentPanel.Children.Add(textBlock);

        childPanel = new DockPanel();
        parentPanel.Children.Add(childPanel);
        parentPanel = childPanel;
    }
}

Дополнительные сведения о логическом дереве см. в разделе Деревья в WPF.

См. также

Основные понятия

Улучшение производительности приложений WPF

Планирование производительности приложения

Оптимизация производительности. Использование преимуществ аппаратного ускорения

Оптимизация производительности: двумерная графика и обработка изображений

Оптимизация производительности: поведение объекта

Оптимизация производительности: ресурсы приложения

Оптимизация производительности: отображение текста

Оптимизация производительности: привязка данных

Оптимизация производительности. Дополнительные рекомендации

Система макета