我知道async void
方法的弊端,但在重写方法时,我并不完全确定解决问题的最佳方法。
说,我有以下代码:
protected override async void PageRefreshed()
{
BoundDataField = await LoadDataFromWeb();
}
我知道这是一件非常糟糕的事情,但对此最好的解决办法是什么?
LoadDataFromWeb().ContinueWith(r => BoundDateField = r.Result);
Task.Run(async ()=> await LoadDataFromWeb())).Wait;
LoadDataFromWeb().Wait
BoundDataField = LoadDataFromWeb.Result
我很确定3& 4是真正的没有,因为他们将阻止UI线程。我错过了另一种解决方案吗?
答案 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;
}
请注意,这个简单的解决方案不能很好地处理错误,也不会处理多个"刷新可能无序更新该字段。更高级的方法是使用Nito.Mvvm.Async
NuGet包中的my NotifyTask<T>
type之类的内容:
protected override void PageRefreshed()
{
BoundDataField = NotifyTask<TData>.Create(LoadDataFromWeb());
}
此方法也需要更新数据绑定代码; BoundDataField.Result
现在是实际数据值,BoundDataField.IsNotCompleted
,BoundDataField.IsFaulted
和其他属性可用于让您的数据绑定响应正在进行或出现故障的状态。