2017-01-20 4 views
1

Я столкнулся с PushFrame метод Dispatcher объект. Это упрощенная версия метода:Для чего нужен PushFrame?

public void PushFrame(DispatcherFrame frame) 
{ 
    // Stuff 
    _frameDepth++; 

    while(frame.Continue) 
    { 
     // Getting and dispatching messages 
    } 

    _frameDepth--; 
    // Stuff 
} 

Другими словами, он просто открывает новый цикл обработки сообщений. Но я действительно не могу понять преимущества такого пути. С каких целей используется PushFrame? Есть ли хорошие примеры его использования? Что касается меня, похоже, что этот метод приведет к очевидным ошибкам.

+1

https://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.pushframe.aspx – crowchirp

+0

Я читаю документацию. Я знаю, как это работает, но я не могу понять цели этого метода. Почему нужен метод PushFrame – LmTinyToon

ответ

6

Это важная сантехника для цикла диспетчера в программе WPF. У каждой программы GUI на Windows есть одно, это универсальное решение для producer-consumer problem. Где создаются ОС и другие программы, а поток пользовательского интерфейса вашей программы WPF потребляет. Жесткое требование для приложений с графическим интерфейсом, библиотечный код, реализующий графический интерфейс, никогда не является потокобезопасным. Вы можете легко увидеть цикл здесь, вы не можете увидеть потокобезопасную очередь, которая освобождается циклом, она встроена в ОС.

Цикл запускается по вызову Application.Run(). В приложении WPF не так просто видеть, что он автоматически генерируется в большинстве приложений из вашего файла App.xaml. Это подталкивает первый «кадр», ваше приложение продолжает работать, пока оно остается внутри цикла. Вы всегда увидите его в окне отладки Call Stack, когда вы устанавливаете точку останова на обработчике событий. Закрытие MainWindow вашего приложения - это нормальный путь завершения цикла. Это, в свою очередь, приводит к возврату метода Run(), который завершает поток пользовательского интерфейса, который завершает процесс.

Есть несколько сценариев, в которых вам нравится иметь вложенный контур диспетчера. «Модальная петля». Пример такого модального цикла, который вы используете каждый день, - это когда вы нажимаете и перетаскиваете мышь в окне окна. Все мыши и клавиатура теперь меняют размер окна или местоположение, они больше не используются для управления интерфейсом пользователя обычным способом. Освобождение мыши завершает этот цикл. Этот цикл диспетчера встроен в ОС, он не выполняется WPF.

Но WPF использует также такую ​​модульную петлю. Канонический пример - это метод Window.ShowDialog(). Этот метод не возвращается, пока диалог не будет закрыт. Достигнут WPF, снова вызвав PushFrame(). Просто попробуйте его с помощью отладчика, вы увидите вызовы PushFrame в окне «Стек вызовов». Первый - тот, который вызвал ShowDialog(), второй - тот, который является Приложением.Вызывается Run(). Вы получите больше, если в диалоговом окне появится диалоговое окно.

Менее очевидным примером является вызов Dispatcher.Invoke() в потоке пользовательского интерфейса. Метод, который не возвращается, пока вызываемый метод не вернется. Обычно это была небольшая ошибка, но не было убедительной причины ее запретить. Слово предупреждения может быть уместным, модальные петли довольно опасны. У них есть умение вызывать ошибки повторного входа. Такая ошибка, которая сделала метод DoEvents() настолько печальным. Большая причина, по которой ShowDialog() отключает все остальные окна вашего пользовательского интерфейса.

+0

Отличное объяснение. благодаря – LmTinyToon

1

Для каких целей используется PushFrame?

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

Understanding the Dispatcher Queue

Есть ли хорошие примеры его использования?

Например, когда вы по какой-либо причине хотите синхронно вызывать метод асинхронного вызова и продолжать передавать сообщения до завершения задачи. Вы можете найти конкретный пример реализации этого в библиотеке AsyncCTPUtil Стивена Клири на GitHub: https://github.com/StephenCleary/AsyncCTPUtil/blob/master/AsyncTestUtilities/WpfContext.cs

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

How would I run an async Task<T> method synchronously?

Вы также можете обратиться к следующей ссылке: https://social.msdn.microsoft.com/Forums/vstudio/en-US/650e69f9-5f4d-4d77-8107-93fb6646f26d/solved-block-synchronous-method-while-waiting-for-async-method-to-complete?forum=wpf

Смежные вопросы