我正在重写MVVM框架的某些部分以利用异步/等待功能,请考虑以下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线程编码。但是,我将两者的性能进行了比较,并且存在显着差异。我执行了1000次循环,其中将对象绑定(bind)到 View ,然后再次设置为null,这是毫秒数的结果:
一个等待调用,任务延迟为10毫秒
带
ConfigureAwait(false)
的三个等待调用,任务延迟为10毫秒
ConfigureAwait(false)
这个基准测试还远未达到完美,但是将属性编码回UI线程似乎比在等待调用后在所有线程上运行所有任务要便宜得多。但是,这需要更多的测试才能为所有情况给出确定的答案。
我只是将其放在此处以证明两者之间存在差异。我的建议是在这种情况下不要使用ConfigureAwait,因为它增加了更改代码时出现异常的机会,可读性较差,并且同事可能不理解这一点,并因此而使用了错误的安全感。
最佳答案
我个人选择将所有数据绑定(bind)属性都视为具有UI亲和力。
原因之一是不同的MVVM框架在这方面具有不同的功能。 WPF确实会为您处理此操作(针对简单属性),而其他人则不会。
当async
放在CTP中时,关于await
的默认行为进行了无数讨论。每种方式都有优点和缺点。
关于c# - 严格的MVVM和Task.ConfigureAwait(false),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26236014/