I'm trying to understand what is the best approach to use when calling an async method that updates my ViewModel. Right now, let's say I have something like this:
View:
private async void NavigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
//Call my ViewModel method to update the data the UI is bound to
}
ViewModel:
public async Task loadData()
{
this.Source = await loadStuffFromDatabaseAsync();
}
Now, I'm not sure which one of the following approaches should I use:
1) In my LoadState method, use:
await Task.Run(async () => { await ViewMode.loadData(); });
2) Use Task.Run without awaiting the loadData method inside the Action :
await Task.Run(() => { ViewModel.loadData(); });
3) Call my loadData method with:
await ViewModel.loadData().ConfigureAwait(false);
4) Call the loadData method without awaiting it in my View class and use Task.Run inside my loadData method:
View:
private void NavigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
ViewModel.loadData();
}
ViewModel:
public async void loadData()
{
await Task.Run(async () =>
{
this.Source = await loadStuffFromDatabaseAsync();
});
}
What are the main differences between these approaces?
Is one more efficient that the other, and should I pick one in particular?
Thanks for your help! :)
Sergio
You should only use Task.Run
if you have CPU-bound or blocking work that you want to move off the UI thread. That's not the case here, so the direct call (option 3) is the most natural.
Taking them in turn:
await Task.Run(async () => { await ViewMode.loadData(); });
This option will execute loadData
on a thread pool thread. This may not work very well, since loadData
is updating the UI (indirectly by setting a VM property). Even if it does happen to work (i.e., some MVVM frameworks can properly handle updates from background threads in some scenarios), it's probably unnecessary since loadData
is an asynchronous method.
Furthermore, it adds async
state machine overhead for no reason.
await Task.Run(() => { ViewModel.loadData(); });
This option has all the same problems, except it's slightly more efficient since it doesn't have the async
state machine overhead. But it's still updating VM properties on a background thread and using a background thread unnecessarily.
public async void loadData()
This one's the worst of all. It inherits the same problems of the others: updating VM properties on a background thread and using an unnecessary background thread. To that it adds the problems of async void
. One problem is that NavigationHelper_LoadState
cannot catch any exceptions from loadData
. Another problem is that loadData
is not easily testable.
So just use the simple approach and call it directly:
await ViewModel.loadData().ConfigureAwait(false);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With