覆盖时异步无效

Ash*_*son 3 c# asynchronous

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

说,我有以下代码:

protected override async void PageRefreshed()
{
    BoundDataField = await LoadDataFromWeb();
}
Run Code Online (Sandbox Code Playgroud)

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

  1. LoadDataFromWeb().ContinueWith(r => BoundDateField = r.Result);
  2. Task.Run(async ()=> await LoadDataFromWeb())).Wait;
  3. LoadDataFromWeb().Wait
  4. BoundDataField = LoadDataFromWeb.Result

我很确定3和4是真的没有,因为他们将阻止UI线程.我错过了另一种解决方案吗?

Ste*_*ary 6

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

不只是阻塞,而且很可能也是死锁.

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

您要做的是异步检索数据绑定属性的值.我在关于异步数据绑定的MSDN文章中详细介绍了这一点.

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

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

所以,你需要妥协:

  • 计算机会立即显示一些占位符数据或微调器或其他内容.
  • 您在到达时使用实际数据更新显示.

这样,代码就更简单了:

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

要么:

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

  // Asynchronously load data and then hide spinner
  BoundDataField = await LoadDataFromWeb();
  IsBusy = false;
}
Run Code Online (Sandbox Code Playgroud)

请注意,这个简单的解决方案不能很好地处理错误,也不能处理可能无序更新该字段的多个"刷新".一种更先进的方法是使用像我的NotifyTask<T>类型Nito.Mvvm.AsyncNuGet包:

protected override void PageRefreshed()
{
  BoundDataField = NotifyTask<TData>.Create(LoadDataFromWeb());
}
Run Code Online (Sandbox Code Playgroud)

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