INotifyPropertyChanged: Должен ли я Marshall до или после вызова? - PullRequest
0 голосов
/ 07 мая 2019

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

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

Когда я добавляю обработчик события, который вызывает ICommand.CanExecuteChanged к событию INotifyPropertyChanged.PropertyChanged, я получаю перекрестную нить InvalidOperationException.

Должен ли я маршалировать обратно в поток пользовательского интерфейса, когда я поднимаю INotifyPropertyChanged.PropertyChanged или когда я поднимаю ICommand.CanExecuteChanged?

Оба варианта имеют свои плюсы и минусы, но в любом случае работают. Что считается лучшей практикой?

Вот плюсы и минусы каждого, чтобы вы понимали, почему я спрашиваю: pros and cons Это всего лишь некоторые из моей головы. Я хотел бы знать, что считается лучшим вариантом и почему. На данный момент я думаю, что сортировка в обработчике - хороший вариант, но он все равно не устраивает меня. Возможно, есть вариант, который я упустил.

1 Ответ

0 голосов
/ 07 мая 2019

Итак, я предполагаю, что ваш код похож на

class MyCustomCommand : ICommand
{
    public event EventHandler CanExecuteChanged;

    // the rest of the ICommand interface members implemented    

    private void HandlePropertyChanged(object sender, NotifyPropertyChangedEventArgs e)
    {
        this.CanExecuteChanged?.Invoke(this, EventArgs.Empty);
    }
}

В этом случае событие CanExecuteChanged команды будет запускаться в том же фоновом потоке.Почему это вызывает межпотоковое исключение, я не знаю - вам придется предоставить больше кода, чтобы продемонстрировать контекст, в котором они используются, в том числе то, как связаны привязки.

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

var dispatcher = GetADispatcherForMarshallingToUI();
dispatcher.BeginInvoke((Action)(() => this.CanExecuteChanged?.Invoke(this, EventArgs.Empty)));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...