Чем Dispatcher отличается от фонового потока? - PullRequest
6 голосов
/ 29 марта 2010

Чем концепция Dispatcher в .NET 3.5 и WPF отличается от фонового потока в .NET 2.0?

Например, какая разница между утверждениями ниже:

delegate.Invoke/BeginInvoke

И

this.dispatcher.Invoke/BeginInvoke

Ответы [ 4 ]

6 голосов
/ 29 марта 2010

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

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

2 голосов
/ 29 марта 2010

Понятие BeginInvoke и Invoke можно представить следующим образом.

  • BeginInvoke означает: «Сделайте это и вернитесь до его завершения. Мне либо наплевать на возвращаемое значение, либо вы можете перезвонить мне по этому адресу в будущем».
  • «Вызывать» означает: «Сделай это, и я сижу здесь и жду, пока оно завершится».

Теперь, как это относится к диспетчерам и фоновым потокам, это совсем другое дело. Как говорит Джастин, диспетчер обрабатывает очередь вещей, которые нужно делать каждый раз, когда поток пользовательского интерфейса становится бездействующим. Фоновый поток, который вызывает BeginInvoke для диспетчера, немедленно вернется, даже если диспетчер, возможно, не дошел до обработки. Если вместо этого использовался Invoke, фоновый поток блокировался до тех пор, пока поток пользовательского интерфейса не завершил обработку. Обратите внимание, что в Silverlight нет Invoke для Dispatcher, и в большинстве случаев вы, вероятно, не хотите, чтобы фоновый поток блокировался, пока поток пользовательского интерфейса обрабатывает работу.

И наоборот, Delegate.BeginInvoke использует рабочие потоки в пуле потоков. Когда вы в потоке пользовательского интерфейса (или в любом другом потоке), вы можете вызывать BeginInvoke и Invoke для делегата. BeginInvoke будет использовать рабочий поток для вызова делегата, используя ту же семантику, которую я описал выше. Однако Invoke не будет использовать другой поток. Это просто вызовет делегат синхронно в контексте вызывающего потока и вернет его после завершения.

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

0 голосов
/ 29 марта 2010

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

0 голосов
/ 29 марта 2010

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

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

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

...