【发布时间】:2014-12-01 21:07:59
【问题描述】:
我正在重写 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,因此这里没有一个属性需要 UI 线程,因此我在任何地方都使用ConfigureAwait(false)。我知道从ObservableCollection 添加/删除时这是不可能的,但这里不是这种情况。
- 此代码是一种好的做法吗?
- 如果是,那么为什么不能将其设为默认行为?不断输入
ConfigureAwait(false)无助于IMO 的可读性
编辑
在与斯蒂芬讨论之后,我得出的结论是,基本上是一样的。
- 如果您使用
ConfigureAwait(false),您是在告诉 WPF 回调不必在 UI 线程上。设置 INotifyProperty 时,WPF 会确保 UI 线程收到通知。 - 如果您不这样做,WPF 确保回调在 UI 线程上并且完全没有问题。
这两种情况都使 WPF 在某些时候执行 UI 线程编组。但是,我比较了两者的性能,并且存在显着差异。我执行了 1000 次循环,其中一个对象被绑定到一个视图,然后再次设置为 null,以下是以毫秒为单位的结果:
一个等待调用,任务延迟为 10 毫秒
- 15623ms 与
ConfigureAwait(false) - 51700ms 没有
三个等待调用,任务延迟为 10 毫秒
- 46917ms 与
ConfigureAwait(false) - 82647ms 没有
这个基准测试远非完美,但似乎将属性编组回 UI 线程比在 await 调用后强制所有内容在同一线程上运行成本更低。然而,这需要更多的测试才能为所有场景给出明确的答案。
我只是将其放在这里以证明两者之间存在差异。我的建议是不要在这种情况下使用 ConfigureAwait,因为它会在更改代码时增加发生异常的机会,可读性较差,并且同事可能不理解这一点并通过使用它来获得错误的安全感。
【问题讨论】:
-
等等,这里没有一个属性需要 UI 线程。你不绑定
View到Dossiers?如果你这样做了,那么你的假设是错误的。 -
正如斯蒂芬所说,WPF 处理简单属性的 UI 线程封送处理
标签: c# wpf mvvm async-await