Async void when overridden
I am aware of the flaws of methods async void
, but not entirely sure about the best way to overcome the problem when overriding methods.
Let's say I have the following code:
protected override async void PageRefreshed()
{
BoundDataField = await LoadDataFromWeb();
}
I know this is very bad, but what's 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 3 and 4 are real no nos as they will block the UI thread. Is there any other solution I missed?
source to share
I'm sure 3 and 4 are real no nos as they will block the UI thread.
Not just blocking, but quite possibly blocking .
Is there any other solution I missed?
What you are trying to do is get the value of the data-bound property asynchronously. I'll cover this in detail in the MSDN article on Asynchronous Data Binding .
First, the central thing to acknowledge is that it is not possible, as written. There are two conflicting requirements:
- The computer should immediately display something.
- You need to display data and it will take time.
So, you need to compromise:
- The computer receives some placeholder data or a counter or something that needs to be displayed right away.
- You update the display with real data when it arrives.
Put this way, the code is more simple:
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 does not handle errors well and also does not handle multiple "updates", possibly updating this field out of order. A more advanced approach is to use my NotifyTask<T>
type from the Nito.Mvvm.Async
NuGet package :
protected override void PageRefreshed()
{
BoundDataField = NotifyTask<TData>.Create(LoadDataFromWeb());
}
This approach requires updating the data binding code; BoundDataField.Result
is now the actual data value BoundDataField.IsNotCompleted
, a BoundDataField.IsFaulted
, and other properties can be used to make your data binding respond to incomplete or corrupted states.
source to share