我最近使用async / await模式将一些代码更改为异步。
此代码现在正在创建一个例外:
private async void Refresh(object stateInfo)
{
await Task.Factory.StartNew(HydrateServerPingDtoList);
// more code here
}
private void HydrateServerPingDtoList()
{
// more code here.
// Exception occurs on this line:
this._serverPingDtoList.Add(new ServerPingDto() { ApplicationServer = server });
}
例外:
此类型的CollectionView不支持对其进行更改 来自与Dispatcher线程不同的线程的SourceCollection。
_serverPingDtoList
是WPF绑定属性的支持字段。由于我认为async-await保留了同步上下文,为什么我会收到此错误?
答案 0 :(得分:11)
await
在自己的SynchronizationContext
方法中恢复async
。它不会将其传播到您通过StartNew
开始的后台线程。
在旁注中,StartNew
代码中不应使用async
;我在我的博客上explain why in detail。您应该使用Task.Run
来执行CPU绑定代码。
但是,任何UI更新(包括数据绑定属性的更新)都应该在UI线程上完成,而不是在后台任务上完成。因此,假设您的HydrateServerPingDtoList
实际上是CPU绑定的,您可以这样做:
private ServerPingDto HydrateServerPingDtoList()
{
// more code here.
return new ServerPingDto() { ApplicationServer = server };
}
private async Task Refresh(object stateInfo)
{
var serverPingDto = await Task.Run(() => HydrateServerPingDtoList());
this._serverPingDtoList.Add(serverPingDto);
// more code here
}