Приложение WPF по умолчанию имеет только один диспетчер. Диспетчер - единственный поток, который позволит вам взаимодействовать с элементами пользовательского интерфейса. Он абстрагирует от вас реализации, поэтому вам нужно беспокоиться только о том, чтобы находиться в потоке пользовательского интерфейса, то есть в Dispatcher.
Если вы пытаетесь напрямую взаимодействовать с визуалом (например, установить текст в текстовом поле с помощью txtBkx.Text = "new"
) из рабочего потока, вам придется переключиться на поток пользовательского интерфейса:
Application.Current.Dispatcher.Invoke(
() => { txtBkx.Text = "new"; });
В качестве альтернативы вы можете использовать SynchronizationContext.Current
(находясь в потоке пользовательского интерфейса) и использовать его для выполнения делегатов в потоке пользовательского интерфейса из другого потока. Как следует заметить, Dispatcher.CurrentDispatcher
не всегда может быть установлено.
Теперь вы можете создавать разные окна WPF в одном приложении и иметь отдельный диспетчер для каждого окна:
Thread thread = new Thread(() =>
{
Window1 w = new Window1();
w.Show();
w.Closed += (sender2, e2) =>
w.Dispatcher.InvokeShutdown();
System.Windows.Threading.Dispatcher.Run();
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
Как следует помнить в MVVM, вы можете обновить модель из потока не из пользовательского интерфейса и вызвать события изменения свойств из потока без пользовательского интерфейса, так как WPF будет маршалировать события PropertyChanged для вас. Повышение CollectionChanged должно быть в потоке пользовательского интерфейса.