Is async / await useless in MVVM?

In MVVM, where ViewModels update views through INotifyPropertyChanged events, there seems to be not much room for the cool async / await function; performing a continuation in the captured caller synchronization context.

So, if so, then who will actually use the async / await functions in a modern user interface application? In this context, β€œwho” may also mean which template, for example. MVC variations.

I can think of the following as a good use of TAP

ViewModel.Age { set { await Model.SetAge(value); NotifyPropertyChanged("Age"); } } 

however, this run on a captured syncContext does not help much. In fact, we could put all this in a model instead.

 Model.Age { set { await SetAge(value); NotifyPropertyChanged("Age"); } } 

and now we would really like syncContext NOT to be captured.

+7
source share
1 answer

In fact, data binding requires INotifyPropertyChanged.PropertyChanged , created in the context of user interface synchronization.

async / await forces you to distinguish between properties (which represent the current state and are always synchronous) and commands (which represent actions and can be synchronous or asynchronous). Property and property setters cannot be async , so your sample code with "asynchronous typing" is not possible.

async includes asynchronous commands. You can use command binding to asynchronously manage routed commands, or pass the async delegate to the DelegateCommand or use your own implementation of ICommand . Whichever way you do this, you will get an async void event handler.

A realistic example is that the properties of a virtual machine set the properties of M in memory and have SaveCommand with an async handler. Typically, async handlers interact with an additional VM property ( SaveInProgress or possibly shared Busy with other async handlers), so that the user interface can respond appropriately when the command is executed (typically at least causing CanExecute return false ).

So your async handler looks something like this:

 private async void SaveCommandExecute() { try { // Set VM property; updates View appropriately. Busy = true; // Do the actual saving asynchronously. await Model.SaveAsync(); } catch (Exception ex) { // Update the VM with error information. Error = ex.Message; } finally { // Let the VM know we're done. Busy = false; } } private void SaveCommandCanExecute() { return !Busy; } 

Note that the VM properties ( Error and Busy ) are updated in the context of the captured user interface.


This illustrates the central concept of async MVVM: commands can be async , but properties (such as Busy ) always represent the current state.

If you add async to an existing MVVM application, you will find that you have several additional properties that indicate a business, as well as possibly updating progress (for example, the percentage is complete). Depending on your application, you can perform several asynchronous operations at the same time. You need to think about good ways to add this information to your ideas; I believe this is the most difficult part of async MVVM applications.

+28
source

All Articles