使用async/await不保留同步上下文?

Bob*_*orn 2 c# wpf async-await

我最近使用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 });
}
Run Code Online (Sandbox Code Playgroud)

例外:

这种类型的CollectionView不支持从与Dispatcher线程不同的线程更改其SourceCollection.

_serverPingDtoList是WPF绑定属性的支持字段.由于我认为async-await保留了同步上下文,为什么我会收到此错误?

Ste*_*ary 11

awaitSynchronizationContext在自己的async方法中恢复.它不会将它传播到您通过它开始的后台线程StartNew.

另外,StartNew不应该在async代码中使用; 我博客上详细解释了原因.您应该使用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
}
Run Code Online (Sandbox Code Playgroud)