Подтвердить что ты не робот

WPF: медленное создание шаблона

У меня есть приложение WPF, и оно медленное.

Это НЕ рендеринг. Во-первых, рендеринг довольно прост, а во-вторых, я смотрел его с помощью WPF Performance Toolkit - ничего.

В моем собственном коде НЕ. Во-первых, модульные тесты работают быстро, а во-вторых, если я заменяю все DataTemplates на пустые, все работает быстро.

Пока, похоже, что медленная часть - это создание экземпляра шаблона. То есть, когда вы запускаете приложение и открываете сложный экран, это занимает много времени. И "много" я ​​имею в виду "много". Иногда может быть целых 3-5 секунд - например, когда есть datagrid со 100 строками. Но когда вы переходите на другую вкладку, а затем возвращаетесь к тому же экрану, она открывается быстро (пока его модель просмотра остается на месте).

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

Кроме того, когда я смотрю на некоторые другие приложения WPF (в частности, ILSpy), они, похоже, работают достаточно быстро, несмотря на большие объемы данных. Это заставляет меня поверить, что я, вероятно, что-то делаю неправильно. Но я не знаю, с чего начать.

Любые идеи? Любые классические ошибки? Любые советы?

4b9b3361

Ответ 1

Мое exerience происходит от работы над приложением отображения разума WPF NovaMind

Несколько месяцев назад мы полностью переписали наш промежуточный уровень, чтобы решить проблемы производительности, которые мы испытали. Вкратце, создание пользовательских элементов управления, казалось, было способом замедлить работу. К сожалению, я не смог найти отличный способ профилировать производительность, поскольку ни WPF Performance Suite, ни коммерческие приложения, такие как ANTS Profiler, не дают вам подробной информации об этой части процесса WPF. (Тогда я спросил этот вопрос)

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

В итоге мы решили проблемы с производительностью, полностью переписав наши элементы управления. Мы также значительно сократили сложность нашего визуального дерева. Прежде чем переписать, один из наших наиболее используемых пользовательских элементов управления, когда он был проверен с помощью Snoop, состоял из 61 другой вещи, теперь есть только 3. По возможности мы добавляли вещи в визуальное дерево по требованию. (Как вы знаете в XAML, даже когда вы устанавливаете вещи в Collapsed, их нужно создать сначала). Наконец, мы были вынуждены написать собственный богатый инструмент визуализации текста, поскольку встроенный RichtextBox смехотворно медленный, а визуальное дерево RichtextBox довольно сложно.

Я не знаю, применим ли это к вашей ситуации, но я бы рекомендовал вам изучить ваши пользовательские элементы управления и посмотреть, сложны ли они. Возможно, у вас есть вещи, которые вы можете обрезать. Низкие висящие фрукты будут частями, которые редко видны или могут создаваться ленивым образом. Вы можете создавать эти части из кода по мере необходимости, а не иметь их в XAML. Это должно помочь вам много.

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

Ответ 3

Пользовательский элемент управления в вашем шаблоне данных - это не совсем плохая идея, но если вы жаждете производительности, вам следует рассмотреть возможность переключения на более легкий контроль. Например, если UserControl просто размещает TextBox, это очень плохая идея, поскольку UserControl состоит из ContentControl, хосты ContentControl ContentPresenter и ContentPresenter будут размещать TextBox, поэтому, если вы заметите свое визуальное дерево, у него есть три новых слоя элементов интерфейса. Сокращение визуального дерева, безусловно, улучшит производительность.

Скорее всего, я бы предложил создать пользовательские элементы управления, которые могут быть полностью новым элементом управления, имеющим несколько свойств зависимостей, которые могут относиться к данным, которые вы хотите представить, и у вас может быть свой собственный шаблон в generic.xaml. Во-вторых, вы можете просто получить элемент управления из существующих элементов управления и переопределить его шаблон по умолчанию в generic.xaml.

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

Изменение темы или шаблона будет медленнее, чем изменение элемента, на котором размещается контент. И пусть элемент имеет шаблон по умолчанию в своем собственном ресурсном словаре.

Ответ 4

  • Попробуйте переместить все ресурсы вверх насколько они пойдут, предпочтительно в App.xaml
  • Проверьте, можете ли вы использовать StaticResource вместо динамических, статические намного быстрее
  • Если возможно, попробуйте использовать depedency свойства в ваших виртуальных машинах, особенно если у вас их много, или если у них много свойств. Это будет препятствовать wpf делать кучу отражения.

Ответ 5

Вы упомянули, что используете DataGrid с, скажем, 100 строк. Вероятным виновником ваших проблем является то, что независимо от того, что вы используете, виртуализация не делает, и поэтому ваше визуальное дерево является гигантским.

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

Я не уверен, если вы используете таблицу данных для каждой строки или какую-то стороннюю сетку, которая связывает столбцы или что-то, но позволяет сказать, что у вас есть 8 столбцов с элементами управления. В зависимости от вашей сетки/проверки/etc, это может быть визуальное дерево из 20-60 элементов в строке. Если у вас есть combobox, каждый элемент в раскрывающемся списке может быть создан для каждой строки.

Чтобы исправить это, нужно просто следить за деталями и принимать меры по ходу:

  • Использовать виртуализационный контроль как можно больше. Это означает, что вы используете виртуальную панель управления внутри элементов управления списком и убедитесь, что ваши сторонние элементы управления также работают (многие элементы управления WPF теперь действуют по умолчанию)
  • Не злоупотребляйте UserControls, составные элементы управления и т.д. Добавление глубины добавляет время, а добавление дополнительной глубины визуального дерева в datatemplate или другой повторяющейся области складывается быстро.
  • Если все остальное не удается, покажите простой экран и добавьте элементы управления через код, чтобы улучшить воспринимаемую производительность.

Ответ 6

Это похоже на проблему, с которой я столкнулся. Я разместил исправление здесь: WPF UI Automation issue. Просто публиковать в интересах поисковиков, так как потребовалось много времени для решения.