Reputation: 173
I'm aware of the evils of async void
methods but am not entirely sure of the best way of over coming the problem when overriding methods.
Say, I have the following code:
protected override async void PageRefreshed()
{
BoundDataField = await LoadDataFromWeb();
}
I know this is a really bad thing to do, but what is the best solution for this?
LoadDataFromWeb().ContinueWith(r => BoundDateField = r.Result);
Task.Run(async ()=> await LoadDataFromWeb())).Wait;
LoadDataFromWeb().Wait
BoundDataField = LoadDataFromWeb.Result
I'm pretty sure that 3 & 4 are real no nos as they will be blocking the UI thread. Is there another solution I have missed?
Upvotes: 3
Views: 1210
Reputation: 457057
I'm pretty sure that 3 & 4 are real no nos as they will be blocking the UI thread.
Not just blocking, but quite possibly deadlocking, too.
Is there another solution I have missed?
What you're trying to do is asynchronously retrieve the value of a data-bound property. I cover this in detail in my MSDN article on asynchronous data binding.
First, the central thing to recognize is that this is impossible, as written. There are two conflicting requirements:
So, you'll need to compromise:
Put this way, the code is more straightforward:
protected override async void PageRefreshed()
{
BoundDataField = "placeholder"; // synchronous immediate placeholder data
BoundDataField = await LoadDataFromWeb(); // asynchronous update
}
or:
protected override async void PageRefreshed()
{
// Synchronously show spinner
IsBusy = true;
// Asynchronously load data and then hide spinner
BoundDataField = await LoadDataFromWeb();
IsBusy = false;
}
Note that this simple solution is not handling errors well and also doesn't handle multiple "refreshing"s possibly updating that field out of order. A more advanced approach is to use something like my NotifyTask<T>
type from the Nito.Mvvm.Async
NuGet package:
protected override void PageRefreshed()
{
BoundDataField = NotifyTask<TData>.Create(LoadDataFromWeb());
}
This approach requires updates to your data binding code as well; BoundDataField.Result
is now the actual data value, and BoundDataField.IsNotCompleted
, BoundDataField.IsFaulted
, and other properties can be used to have your data binding respond to in-progress or faulted states.
Upvotes: 7