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

时间:2013-11-01 18:29:11

标签: 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 });
}

例外:

  

此类型的CollectionView不支持对其进行更改   来自与Dispatcher线程不同的线程的SourceCollection。

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

1 个答案:

答案 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
}