Я переписываю некоторые части нашей инфраструктуры 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 выполнять сортировку потоков пользовательского интерфейса в какой-то момент. Тем не менее, я сравнил производительность этих двух, и есть существенная разница. Я выполнил цикл 1000 раз, когда объект привязан к представлению, а затем снова установлен на null, вот результаты в миллисекундах:
Один ожидание вызова с задержкой задачи 10 мс
ConfigureAwait(false)
Три вызова ожидания с задержкой задачи 10 мс
ConfigureAwait(false)
Этот тест далеко не идеален, но кажется, что перенаправление свойств в поток пользовательских интерфейсов является менее дорогостоящим, чем обязательным для всех после вызова ожидания для запуска в одном потоке. Это требует больше тестирования, чтобы дать окончательный ответ для всего сценария.
Я просто помещаю это здесь, чтобы подтвердить, что между ними существуют различия. Мой совет состоял бы в том, чтобы не использовать ConfigureAwait в этом сценарии, поскольку он повышает вероятность исключений при изменении кода, менее читабельен, и коллеги могут не понимать эту точку и получать ложное ощущение безопасности, используя это.
Является ли этот код хорошей практикой?
Лично я предпочитаю обрабатывать все связанные с данными свойства, как если бы они имели UI-сродство.
Одна из причин заключается в том, что разные структуры MVVM имеют разные возможности в этом отношении; это правда, что WPF справится с этим для вас (для простых свойств), но другие не будут.
Если да, то почему вы не можете сделать это по умолчанию?
Когда async
был в CTP, было много обсуждений относительно этого поведения по умолчанию await
. Есть плюсы и минусы каждый путь.
"Я знаю, что это невозможно при добавлении/удалении из коллекции ObservableCollection, но здесь это не так". Это также возможно, если вы используете BindingOperations.EnableCollectionSynchronization.
View
сDossiers
? Если вы это сделаете, то ваше предположение неверно.