Предварительная загрузка окна WPF (возможно, в другом потоке) для повышения производительности - PullRequest
3 голосов
/ 09 июня 2011

У меня есть окно WPF, создание и показ которого занимает много времени.Пользователь должен иметь возможность открыть еще одно или несколько из этих окон.Сейчас я ищу способ улучшить производительность.Одна из идей заключается в создании двух этих окон при запуске приложения (когда оно показывает заставку).После этого мне остается только показать и скрыть эти окна (и изменить прикрепленную модель просмотра).Это не должно быть проблемой.Но когда пользователь работает с приложением и использует два окна, которые загружаются при запуске приложения, я должен загрузить третий экземпляр окна в фоновом режиме.Теперь приложение не должно быть заблокировано, когда оно загружает третье (или 4. или 5. и т. Д.).Сейчас я ищу способ сделать это.Можно ли загрузить окно в другой поток и после передачи его в основной поток пользовательского интерфейса?Или есть другие сценарии для достижения цели?

Спасибо за любую помощь.

С наилучшими пожеланиями, Томас

Ответы [ 6 ]

6 голосов
/ 07 октября 2012

У меня было вторичное окно wpf, которое открывалось долго (2 секунды) при первом его отображении и очень мало времени при последующих загрузках. Оказалось, что это связано с загрузкой расширенной сборки инструментария (и нескольких других). Чтобы исправить это, я добавил в свой файл App.xaml.cs следующее:

        var thread = new Thread(() =>
        {//Force runtime to pre-load all resources for secondary windows so they will load as fast as possible
            new SecondaryForm1();
            new SecondaryForm2();
        });
        thread.SetApartmentState(ApartmentState.STA);
        thread.Priority = ThreadPriority.Lowest;//We don't want prefetching to delay showing of primary window
        thread.Start();
        //Now start primary window

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

5 голосов
/ 10 июня 2011

Когда вы создаете объект WPF - Окно , UserControl или что-либо еще, что происходит от DispatcherObject - он блокируется в потоке, которым он был создано на. Таким образом, вы не можете загрузить окно в фоновом потоке, а затем перенести его в основной поток пользовательского интерфейса. Если вы собираетесь создать его в фоновом потоке, он должен оставаться в этом потоке; он должен быть показан этим потоком и иметь сообщение сообщений в этом потоке.

Но это жизнеспособно. Вы можете запустить фоновый поток, создать там свое окно, а затем подождать, пока основной поток скажет: «Хорошо, пришло время показать окно». Тогда ваш поток может вызвать Application.Run , чтобы запустить собственный насос сообщений и отключиться при закрытии окна.

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

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

4 голосов
/ 09 июня 2011

Может быть, вы пытаетесь решить проблему не с той стороны? Я думаю, что вы должны делать длительные операции, которые заставляют окна зависать в фоновом режиме, а не пытаться запускать окна в фоновом режиме. Вы можете сразу показать окно для пользователей, а затем показать хорошую анимацию, в то время как фоновые потоки выполняют свою работу, получая данные / вычисляя что-то / и т.д. Может быть, я неправильно понял ваш вопрос

1 голос
/ 09 июня 2011

Следите за тем, что сказал Тарас. Обычно такие технологии, как winforms и wpf, достаточно быстры для создания пользовательского интерфейса. Когда вы видите медленный интерфейс, дважды проверьте свой собственный код: Вы загружаете десятки тысяч строк (тогда используйте пейджинг). Вы вызываете медленный метод (вызываете его асинхронно) Вы делаете много звонков в базу данных или сеть? (Бах звонки или положить их в другой поток)

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

1 голос
/ 09 июня 2011

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

1 голос
/ 09 июня 2011

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

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

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