覆盖

时间:2017-07-27 13:49:41

标签: c# asynchronous

我知道async void方法的弊端,但在重写方法时,我并不完全确定解决问题的最佳方法。

说,我有以下代码:

protected override async void PageRefreshed()
{
    BoundDataField = await LoadDataFromWeb();
}

我知道这是一件非常糟糕的事情,但对此最好的解决办法是什么?

  1. LoadDataFromWeb().ContinueWith(r => BoundDateField = r.Result);
  2. Task.Run(async ()=> await LoadDataFromWeb())).Wait;
  3. LoadDataFromWeb().Wait
  4. BoundDataField = LoadDataFromWeb.Result
  5. 我很确定3& 4是真正的没有,因为他们将阻止UI线程。我错过了另一种解决方案吗?

1 个答案:

答案 0 :(得分:6)

  

我很确定3& 4是真的没有,因为他们将阻止UI线程。

不仅仅是阻止,还有quite possibly deadlocking

  

我错过了另一种解决方案吗?

您尝试执行的操作是异步检索数据绑定属性的值。我在MSDN article on asynchronous data binding中详细介绍了这一点。

首先,要认识到的核心是这是不可能的,正如所写的那样。有两个相互矛盾的要求:

  • 计算机必须立即显示内容。
  • 您需要显示数据,这需要时间。

所以,你需要妥协:

  • 计算机会立即显示一些占位符数据或微调器或其他东西。
  • 使用实际数据到达时更新显示。

这样,代码就更简单了:

protected override async void PageRefreshed()
{
  BoundDataField = "placeholder"; // synchronous immediate placeholder data
  BoundDataField = await LoadDataFromWeb(); // asynchronous update
}

或:

protected override async void PageRefreshed()
{
  // Synchronously show spinner
  IsBusy = true;

  // Asynchronously load data and then hide spinner
  BoundDataField = await LoadDataFromWeb();
  IsBusy = false;
}

请注意,这个简单的解决方案不能很好地处理错误,也不会处理多个&#34;刷新可能无序更新该字段。更高级的方法是使用Nito.Mvvm.Async NuGet包中的my NotifyTask<T> type之类的内容:

protected override void PageRefreshed()
{
  BoundDataField = NotifyTask<TData>.Create(LoadDataFromWeb());
}

此方法也需要更新数据绑定代码; BoundDataField.Result现在是实际数据值,BoundDataField.IsNotCompletedBoundDataField.IsFaulted和其他属性可用于让您的数据绑定响应正在进行或出现故障的状态。