Почему использование перьев с шаблонами штрихов приводит к значительному (!) Снижению производительности в пользовательском двумерном чертеже WPF?

Надеюсь, кто-нибудь может пролить свет на это, чтобы я мог использовать ручки с рисунками тире?

Я пишу таблицу с прокруткой (Panel внутри ScrollViewer который реализует IScrollInfo) в WPF используя DrawingVisual"s DataContext.DrawХ. У меня несколько тысяч DrawingVisualс помощью прокрутки TranslateTransform на Panel который принимает их. Я реализовал сетку, поместив Panel поверх него и рисуя простые горизонтальные линии от одного края до другого, используя DataContext.DrawLine(pen, new Point(0, y), new Point(widthOfPanel, y)); //(примечание: эти строки всегда статичны, они никогда не двигаются).

Производительность прокрутки абсолютно безумна (то есть DrawingVisual отрисовывается мгновенно, а прокрутка - мгновенная). Но если я использую Pen который использует штриховые шаблоны (см., например, ниже) для рисования линий сетки, тогда прокрутка очень прерывистая, и производительность, кажется, снизилась в 100 раз (оценка). Может кто-нибудь объяснить, почему это происходит и как я могу обойти это?

Пример пера с рисунком тире:

<Pen x:Key="PenUsingDashPatterns" Brush="Black" Thickness="1">
   <Pen.DashStyle >
      <DashStyle Dashes="3, 3" />
   </Pen.DashStyle>
</Pen>

4 ответа

Решение

Ручки замерзают? Замораживание объектов рисования очень помогает производительности.

Вы можете настроить обработчик Loaded и отладку, чтобы увидеть, не заморожены ли ваши ручки. Если нет, нажмите на них кнопку Pen.Freeze() вручную.

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

Вот возможный обходной путь - если вы рисуете только горизонтальные и / или вертикальные линии, вы можете попробовать создать свой Pen с рисунком шашки DrawingBrush такие как:

  <Pen x:Key="PenUsingDashPatterns" Thickness="1">
        <Pen.Brush>
            <DrawingBrush TileMode="Tile" 
                          Viewport="0 0 6 6" ViewportUnits="Absolute">
                <DrawingBrush.Drawing>
                    <GeometryDrawing Brush="Black">
                        <GeometryDrawing.Geometry>
                            <GeometryGroup>
                                <RectangleGeometry  Rect="0 0 3 3"/>
                                <RectangleGeometry  Rect="3 3 3 3"/>
                            </GeometryGroup>
                        </GeometryDrawing.Geometry>
                    </GeometryDrawing>
                </DrawingBrush.Drawing>
            </DrawingBrush>
        </Pen.Brush>
    </Pen>   

В качестве альтернативы, вы можете использовать разные кисти для вертикальных и горизонтальных линий, или, возможно, ImageBrush для лучшей производительности.

Вы должны использовать Perforator, чтобы углубиться в проблему производительности. Вот ссылка на сайт MSDN, рассказывающая о различных инструментах производительности WPF. Perforator, вероятно, будет инструментом, который поможет вам больше всего, особенно в определении того, нарисованы ли линии с использованием программного средства рендеринга (что будет самым большим фактором, обеспечивающим вам такую ​​плохую производительность).

Если проблема в том, что они рисуются в программном обеспечении, вам, возможно, придется написать свой собственный ShaderEffect, но это, вероятно, будет сложно быстро, если вы не знакомы с HLSL.

Скорее всего, это связано с тем, что эта конкретная операция рисования не может быть делегирована на видеокарту, что приведет к наложению композиции в памяти и разрыву видеокарты.

Другие вопросы по тегам