Обеспечение того, чтобы все выполнялось в потоке пользовательского интерфейса в WPF

Я создаю приложение WPF. Я выполняю асинхронную связь с серверной частью, и я использую агрегацию событий с Prism на клиенте. Обе эти вещи приводят к появлению новых потоков, которые не являются потоком пользовательского интерфейса. Если я попытаюсь выполнить "операции WPF" в этих потоках обратного вызова и обработчика событий, мир распадается, и теперь он начал делать.

Сначала я встретил проблемы с попыткой создать некоторые объекты WPF в обратном вызове с сервера. Мне сказали, что поток нужен для запуска в режиме STA. Теперь я пытаюсь обновить некоторые данные пользовательского интерфейса в обработчике событий Prism, и мне сказали, что:

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

Итак, Какой ключ к правильному использованию WPF? Я прочитал в Диспетчере WPF в этот пост MSDN. Я начинаю это делать, но пока я еще не волшебник.

  • Является ли ключ всегда использовать Dispatcher.Invoke, когда мне нужно запустить что-то, что я не уверен, будет вызван в потоке пользовательского интерфейса?
  • Неважно, действительно ли он был вызван в потоке пользовательского интерфейса, и я все равно Dispatcher.Invoke?
  • Dispatcher.Invoke = синхронно. Dispathcher.BeginInvoke = async?
  • Будет ли Dispatcher.Invoke запрашивать поток пользовательского интерфейса, а затем перестать его ждать? Это плохая практика и риск менее гибких программ?
  • Как мне получить диспетчер? Будет ли Dispatcher.CurrentDispatcher всегда давать мне диспетчер, представляющий поток пользовательского интерфейса?
  • Будет ли более одного диспетчера или "Диспетчер" в основном такой же, как поток пользовательского интерфейса для приложения?
  • А какая сделка с BackgroundWorker? Когда я использую это вместо этого? Я предполагаю, что это всегда асинхронно?
  • Будет ли запущено все, что работает в потоке пользовательского интерфейса (путем вызова), в режиме квартиры STA? То есть если у меня есть что-то, что требуется для запуска в режиме STA - будет ли Dispatcher.Invoke достаточно?

Кто-нибудь хочет очистить вещи для меня? Любые соответствующие рекомендации и т.д.? Благодарю!

Ответ 1

Переходя по каждому из ваших вопросов, один за другим:

  • Не совсем; вы должны только ссылаться на поток пользовательского интерфейса, когда это необходимо. См. № 2.
  • Да, это имеет значение. Вы не должны просто автоматически Invoke все. Ключ должен при необходимости только ссылаться на поток пользовательского интерфейса. Для этого вы можете использовать метод Dispatcher.CheckAccess.
  • Это правильно.
  • Также правильно, и да, вы рискуете менее гибкими программами. В большинстве случаев вы не увидите серьезный удар производительности (мы говорим о миллисекундах для контекстного переключателя), но при необходимости вы должны Invoke. При этом в некоторых случаях это неизбежно, поэтому нет, я бы не сказал, что это плохая практика. Это всего лишь одно решение проблемы, с которой вы будете сталкиваться время от времени.
  • В каждом случае, который я видел, я выполнил с помощью Dispatcher.CurrentDispatcher. Для сложных сценариев этого может быть недостаточно, но я (лично) их не видел.
  • Не совсем правильно, но эта линия мышления не принесет никакого вреда. Позвольте мне сказать так: Dispatcher может использоваться для доступа к потоку пользовательского интерфейса для приложения. Но это не сам по себе поток пользовательского интерфейса.
  • BackgroundWorker обычно используется, когда у вас есть трудоемкая операция и вы хотите поддерживать отзывчивый интерфейс при выполнении этой операции в фоновом режиме. Обычно вы не используете BackgroundWorker вместо Invoke, а используете BackgroundWorker вместе с Invoke. То есть, если вам нужно обновить некоторый объект пользовательского интерфейса в BackgroundWorker, вы можете вызвать в поток пользовательского интерфейса, выполнить обновление и вернуться к исходной операции.
  • Да. Потоки пользовательского интерфейса приложения WPF по определению должны работать в однопоточной квартире.

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