Вопрос

Я заметил, что запуск приложения WPF иногда происходит довольно медленно.Кто-нибудь знает, является ли причиной инициализация элементов или загрузка DLL или что-то еще?

Это было полезно?

Решение

Приведенный ниже текст был извлечен из эта статья MSDN об улучшении времени запуска приложений WPF (Редактировать:теперь слились в Время запуска приложения WPF)

Время запуска приложения

Количество времени, необходимое для запуска приложения WPF, может сильно различаться.В этом разделе описываются различные методы сокращения предполагаемого и фактического времени запуска приложения Windows Presentation Foundation (WPF).

Понимание холодного запуска и теплого запуска

Холодный запуск происходит, когда ваше приложение запускается в первый раз после перезагрузки системы или когда вы запускаете свое приложение, закрываете его, а затем запускаете снова через длительный промежуток времени.При запуске приложения, если требуемые страницы (код, статические данные, реестр и т.д.) отсутствуют в списке ожидания диспетчера памяти Windows, возникают ошибки страниц.Для переноса страниц в память требуется доступ к диску.

Быстрый запуск происходит, когда большинство страниц для основных компонентов common language runtime (CLR) уже загружены в память, что экономит дорогостоящее время доступа к диску.Вот почему управляемое приложение запускается быстрее при повторном запуске.

Внедрить экран-заставку

В случаях, когда существует значительная, неизбежная задержка между запуском приложения и отображением первого пользовательского интерфейса, оптимизируйте воспринимаемое время запуска с помощью экран - заставка.При таком подходе изображение отображается почти сразу после того, как пользователь запускает приложение.Когда приложение будет готово к отображению своего первого пользовательского интерфейса, экран-заставка исчезнет.Начиная с .NET Framework 3.5 SP1, вы можете использовать Экран - заставка класс для реализации заставки.Для получения дополнительной информации см. Как сделать:Добавление заставки в приложение WPF.

Вы также можете реализовать свою собственную заставку, используя встроенную графику Win32.Покажите свою реализацию перед Беги вызывается метод.

Проанализируйте код запуска

Определите причину медленного холодного запуска.Дисковый ввод-вывод может быть ответственным, но это не всегда так.Как правило, вам следует свести к минимуму использование внешних ресурсов, таких как сеть, веб-службы или диск.

Перед тестированием убедитесь, что никакие другие запущенные приложения или службы не используют управляемый код или код WPF.

Запустите свое приложение WPF сразу после перезагрузки и определите, сколько времени требуется для его отображения.Если все последующие запуски вашего приложения (теплый запуск) выполняются намного быстрее, проблема с холодным запуском, скорее всего, вызвана вводом-выводом.

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

Оптимизация загрузки модуля

Используйте такие инструменты, как Process Explorer (Procexp.exe) и Tlist.exe чтобы определить, какие модули загружает ваше приложение.Список команд <pid> показывает все модули, которые загружены процессом.

Например, если вы не подключаетесь к Интернету и видите, что загружено System.Web.dll, значит, в вашем приложении есть модуль, который ссылается на эту сборку.Проверьте, чтобы убедиться, что ссылка необходима.

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

Отложить Операции инициализации

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

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

Избегайте настройки приложения

Подумайте о том, чтобы избежать настройки приложения.Например, если приложение имеет простые требования к конфигурации и строго регламентирует время запуска, записи реестра или простой INI-файл могут быть альтернативой более быстрому запуску.

Используйте GAC

Если сборка не установлена в Глобальном кэше сборок (GAC), возникают задержки, вызванные проверкой хэша сборок со строгими именами и проверкой образа Ngen, если на компьютере доступен собственный образ для этой сборки.Проверка строгого имени пропускается для всех сборок, установленных в GAC.Для получения дополнительной информации см. Gacutil.exe (Инструмент глобального кэша сборок).

Использование Ngen.exe

Рассмотрите возможность использования собственного генератора изображений (Ngen.exe) в вашем приложении.Использование Ngen.exe означает обмен потреблением процессора на больший доступ к диску, поскольку исходное изображение, сгенерированное Ngen.exe, вероятно, будет больше, чем изображение MSIL.

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

В некоторых сценариях холодного запуска также может быть полезным использование Ngen.exe.Это происходит потому, что JIT-компилятор (mscorjit.dll) не обязательно загружать.

Наличие как модулей Ngen, так и JIT может иметь наихудший эффект.Это потому, что mscorjit.dll необходимо загрузить, и когда JIT-компилятор работает над вашим кодом, многие страницы в изображениях Ngen должны быть доступны, когда JIT-компилятор считывает метаданные сборок.

Ngen и ClickOnce

Способ, которым вы планируете развернуть свое приложение, также может повлиять на время загрузки.Развертывание приложения ClickOnce не поддерживает Ngen.Если вы решите использовать Ngen.exe для вашего приложения вам придется использовать другой механизм развертывания, такой как установщик Windows.

Для получения дополнительной информации см. Ngen.exe (Собственный генератор изображений).

Перебазирование и конфликты адресов DLL

Если вы используете Ngen.exe, имейте в виду, что перебазирование может произойти при загрузке собственных изображений в память.Если библиотека DLL не загружена по предпочтительному базовому адресу, поскольку этот диапазон адресов уже выделен, загрузчик Windows загрузит ее по другому адресу, что может занять много времени.

Вы можете использовать дамп виртуальных адресов (Vadump.exe), чтобы проверить, есть ли модули, в которых все страницы являются частными.Если это так, возможно, модуль был перенесен на другой адрес.Следовательно, его страницы не могут быть общедоступными.

Дополнительные сведения о том, как задать базовый адрес, см. Ngen.exe (Собственный генератор изображений).

Оптимизировать Аутентификационный код

Проверка подлинности увеличивает время запуска.Сборки, подписанные Authenticode, должны быть проверены центром сертификации (CA).Эта проверка может занять много времени, поскольку для загрузки текущих списков отзыва сертификатов может потребоваться подключение к сети несколько раз.Это также гарантирует наличие полной цепочки действительных сертификатов на пути к доверенному корню.Это может привести к задержке в несколько секунд во время загрузки сборки.

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

Начиная с .NET Framework 3.5, существует параметр конфигурации, который позволяет обойти проверку Authenticode.Чтобы сделать это, добавьте следующую настройку в файл app.exe.config:

<configuration>
 <runtime>
    <generatePublisherEvidence enabled="false"/>
  </runtime>
</configuration>

Сравните производительность в Windows Vista

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

Этот подход отличается от метода предварительной выборки, используемого в Windows XP, который предварительно загружает данные в память без анализа шаблонов использования.Со временем, если пользователь часто использует ваше приложение WPF в Windows Vista, время "холодного" запуска вашего приложения может увеличиться.

Эффективно используйте домены приложений

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

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

Используйте атрибут NeutralResourcesLanguage

Используйте Атрибут NeutralResourcesLanguageAttribute Нейтральный языковой ресурс чтобы указать нейтральную культуру для Менеджер ресурсов.Такой подход позволяет избежать неудачных поисков сборки.

Используйте класс BinaryFormatter для сериализации

Если вам необходимо использовать сериализацию, используйте Двоичный форматировщик класс вместо XmlSerializer - Сериализатор класс.В Двоичный форматировщик класс реализован в библиотеке базовых классов (BCL) в сборке mscorlib.dll.В XmlSerializer - Сериализатор реализован в сборке System.Xml.dll, которая может быть дополнительной библиотекой DLL для загрузки.

Если вы должны использовать XmlSerializer - Сериализатор класс, вы можете добиться более высокой производительности, если предварительно сгенерируете сборку сериализации.

Настройте ClickOnce для проверки наличия обновлений после запуска

Если ваше приложение использует ClickOnce, избегайте доступа к сети при запуске, настроив ClickOnce на проверку сайта развертывания на наличие обновлений после запуска приложения.

Если вы используете модель XAML browser application (XBAP), имейте в виду, что ClickOnce проверяет сайт развертывания на наличие обновлений, даже если XBAP уже находится в кэше ClickOnce.Для получения дополнительной информации см. Безопасность и развертывание ClickOnce.

Настройте службу PresentationFontCache для автоматического запуска

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

Программно установите Привязку данных

Вместо того, чтобы использовать XAML для установки DataContext - Текст данных декларативно для главного окна, рассмотрите возможность установки его программно в Активированный способ.

Другие советы

Время запуска приложения WPF может быть намного быстрее, если вы используете Framework 3.51, а не 3.5 или 3.0.3.51 - это действительно улучшение.

Был дан самый полезный совет по исправлению производительности запуска WPF, который я когда-либо видел в этом другом вопросе:запустите "обновление ngen" в каждой папке framework.

Похоже, что Microsoft не может поддерживать свой кэш ngen в актуальном состоянии, что приводит к тому, что ваше приложение в значительной степени перекомпилирует половину .NET framework при каждом запуске.

Трудно поверить, но, похоже, это правда.

Это старая тема, но я несколько раз оказывался здесь, пытаясь устранить проблему с производительностью запуска приложений WPF в моей системе Win10, поэтому я подумал, что приведу ответ, который может помочь другим - ответ, который занимает ужасное 5-секундное время запуска для всех приложений WPF в этой системе, сокращенное всего до нескольких миллисекунд. Удалите драйвер nVidia "3d Vision".У меня есть карта GeForce GTX 650, и драйвер "3d Vision", похоже, не предлагает ничего полезного, поэтому удалить его для меня не проблема.Инструмент анализа производительности VisualStudio2015, наконец, помог показать, что почти все 5-секундное время запуска было потрачено в режиме ожидания после вызова через nvapi64.dll - драйвер nVidia.Вау.

Что мне больше всего помогло в отличной статье, на которую ссылается Стюарт, так это трюк с XmlSerializer.Это действительно сэкономило немало секунд.Кроме того, не стоит недооценивать дефрагментацию вашего HD :-)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top