строгий MVVM и Task.ConfigureAwait (false)

1

Я переписываю некоторые части нашей инфраструктуры MVVM, чтобы использовать функции async/await, рассмотрим следующий код VM:

private async Task LoadDossier(int ID)
    {
        //VM INotifyProperty
        Dossiers = new ObservableCollection<Dossier>(await BubManager.GetAllBubDossiersForEmployeeByDossierIdAsync(ID).ConfigureAwait(false));
        //VM INotifyProperty
        SelectedDossier = Dossiers.First(x => x.Id == ID);
        //VM INotifyProperty
        DossierEmployer = await EmployerManager.GetEmployerByIdAsync(SelectedDossier.EmployerId).ConfigureAwait(false);
        //VM INotifyProperty
        DossierEmployee = await EmployeeManager.GetEmployeeByIdAsync(SelectedDossier.EmployeeId).ConfigureAwait(false);
        //All VM INotifyProperties
        if (SelectedDossier != null && DossierEmployer != null)
        {
            RszNr = DossierEmployer.RszNr;
            FundsNr = DossierEmployer.FundsNr;
            RrNr = DossierEmployee.RrNr;
        }
        RefreshGlobalCommanding();
    }

Поскольку я использую строгий MVVM, здесь нет ни одного свойства, для которого нужен поток пользовательского интерфейса, поэтому я везде использую ConfigureAwait(false). Я знаю, что это невозможно при добавлении/удалении из ObservableCollection, но здесь это не так.

  • Является ли этот код хорошей практикой?
  • Если да, то почему вы не можете сделать это по умолчанию? Постоянно набирать ConfigureAwait(false) не помогает читабельности IMO

РЕДАКТИРОВАТЬ

После обсуждения со Стефаном я пришел к выводу, что это в основном то же самое.

  • Если вы используете ConfigureAwait(false), вы сообщаете WPF, что обратный вызов не обязательно должен быть в потоке пользовательского интерфейса. При установке INotifyProperty WPF гарантирует, что поток пользовательского интерфейса получит уведомление.
  • Если вы не используете WPF, убедитесь, что обратный вызов включен в поток пользовательского интерфейса, и проблем нет.

Оба случая заставляют WPF выполнять сортировку потоков пользовательского интерфейса в какой-то момент. Тем не менее, я сравнил производительность этих двух, и есть существенная разница. Я выполнил цикл 1000 раз, когда объект привязан к представлению, а затем снова установлен на null, вот результаты в миллисекундах:

Один ожидание вызова с задержкой задачи 10 мс

  • 15623мс с ConfigureAwait(false)
  • 51700 мс без

Три вызова ожидания с задержкой задачи 10 мс

  • 46917мс с ConfigureAwait(false)
  • 82647 мс без

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

Я просто помещаю это здесь, чтобы подтвердить, что между ними существуют различия. Мой совет состоял бы в том, чтобы не использовать ConfigureAwait в этом сценарии, поскольку он повышает вероятность исключений при изменении кода, менее читабельен, и коллеги могут не понимать эту точку и получать ложное ощущение безопасности, используя это.

  • 0
    Подождите, здесь нет ни одного свойства, которому нужен поток пользовательского интерфейса . Вы не связываете View с Dossiers ? Если вы это сделаете, то ваше предположение неверно.
  • 1
    Как сказал Стивен, WPF обрабатывает маршалинг потока пользовательского интерфейса для простых свойств.
Теги:
wpf
async-await
mvvm

2 ответа

3
Лучший ответ

Является ли этот код хорошей практикой?

Лично я предпочитаю обрабатывать все связанные с данными свойства, как если бы они имели UI-сродство.

Одна из причин заключается в том, что разные структуры MVVM имеют разные возможности в этом отношении; это правда, что WPF справится с этим для вас (для простых свойств), но другие не будут.

Если да, то почему вы не можете сделать это по умолчанию?

Когда async был в CTP, было много обсуждений относительно этого поведения по умолчанию await. Есть плюсы и минусы каждый путь.

  • 0
    Что такое простые свойства и тогда они становятся не такими простыми? У меня были некоторые ошибки при попытке привязки к свойствам, которые были изменены в другом потоке, поэтому мне очень любопытно.
  • 0
    Спасибо за ответ ниндзя Стивену (и за все хорошие посты в блогах, которые вы сделали по этой теме). Но если я правильно понимаю, этот конкретный сценарий является допустимым кодом и будет работать немного лучше, чем без использования ConfigureAwait, правильно?
Показать ещё 4 комментария
0

"Я знаю, что это невозможно при добавлении/удалении из коллекции ObservableCollection, но здесь это не так". Это также возможно, если вы используете BindingOperations.EnableCollectionSynchronization.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню