Общий подход состоит в том, чтобы иметь свойство Dispatcher в вашей модели представления (возможно, в базовом классе для всех моделей представления), которое можно вводить извне.Это нормально, чтобы иметь его в модели представления, потому что модель представления ДОЛЖНА знать о концепциях пользовательского интерфейса, но она не должна знать о конкретном представлении (макет, элементы управления и т. Д.) И, конечно, не должна иметь ссылку на представление.
Что вы можете сделать, так это упростить отправку кода в поток Dispatcher, создав помощника или службу, которая будет абстрагировать диспетчера.Например, вы можете создать помощника следующим образом:
public class AsyncHelper
{
public static void EnsureUIThread(Action action)
{
if (Application.Current != null && !Application.Current.Dispatcher.CheckAccess())
{
Application.Current.Dispatcher.BeginInvoke(action, DispatcherPriority.Background);
}
else
{
action();
}
}
}
И всякий раз, когда вам нужно обновить наблюдаемую коллекцию, вы заключаете код в этот метод помощника:
AsyncHelper.EnsureUIThread(() =>
{
// Update you observable collections here
});
ИЛИ,Вы можете пойти дальше и использовать AOP (например, PostSharp ), чтобы декларативно (с использованием атрибутов) указать, что метод должен выполняться в потоке пользовательского интерфейса.
И, наконец, обратите внимание, что вы должныотправлять только обновления коллекции в поток пользовательского интерфейса.Обычные свойства могут быть безопасно обновлены из фонового потока.Обновления будут автоматически отправляться в поток пользовательского интерфейса с помощью механизма привязки.Вероятно, в будущих версиях WPF также будут поддерживаться обновления коллекции из фонового потока.