MVVM AsyncDelegateCommand – what async/await can do for UI development

It is all about User Experience (UX) these days. And nothing is more annoying than frozen user interfaces. How much time have I spent in front of frozen user interfaces watching this neat little hourglass cursor.  I don’t want my users waste their time watching fancy cursors, I want them to be users of software that doesn’t dictate their habits. One of the pieces in this puzzle is a (guess!) responsive user interface. Users should not be surprised by good UIs, they should be annoyed at bad ones. Responsiveness is a key factor in my opinion.

Today I’ll make an attempt to show how async & await can be used to implement an asynchronous version of the System.Windows.Input.ICommand interface that drastically simplifies the way we can use asynchronous commands within our view models (in an MVVM sense). I will (in a future post – expect future to be “sooner than ever”) also provide a decorator for any other (already existing) ICommand implementation that will convert the initial synchronous call into an asynchronous one and still provide all features the async version has to offer. Since everybody should be free in choosing her favorite MVVM framework (that most likely provide an implementation of ICommand, e.g. the well-known DelegateCommand or RelayCommand) and benefit from just decorating the existing commands.

So let’s get down to business…

The ICommand interface is quite simple, it only requires us to implement two methods and one event.

public interface ICommand
{
    bool CanExecute(object parameter);
    void Execute(object parameter);
    event EventHandler CanExecuteChanged;
}

Exposing properties of type ICommand in view models is daily business in WPF applications using MVVM pattern, as this enables command-binding in the view. As I said before, there exist a lot of different implementations of this interface. Most of them are synchronous implementations, some of them are asynchronous implementations enabling pre- and post-processing as well as scheduling the actual command on some kind of background task. So – asynchronous ICommand implementations are nothing new in itself. But the way we can use them has changed since the MS guys gave us async & await. It is much more simple these days…

So when we are actually implementing this interface, we can use the new async modifier (see MSDN for details on async/await) with the Execute(object) method. This allows the use of the await keyword within the method which finally turns the method into an asynchronous call – without having to provide callbacks on our own (or any other mechanism to end an asynchronous call). The compiler takes care of all this stuff. I definitely recommend reading through the documentation of async & await, if you are not already familiar with these concepts. It is really great stuff.

public async void Execute(object parameter)
{
    await ExecuteAsync(parameter);
}

Within the Execute(object) method we just delegate the call to a ExecuteAsync(object) method, that is called according to the naming conventions. I decided to give it protected visibility, so inheritors can provide their own implementation.

protected virtual async Task ExecuteAsync(object parameter)
{
    await _asyncExecute(parameter);
}

The _asyncExecute field used here is the usual delegate that is supplied to be invoked when the ICommand.Execute(object) is called. As the method shows, we do nothing else than invoke the delegate. The member _asyncExecute member that is used in this method is a Func<object, Task> that must be provided during construction of the class.

protected readonly Predicate<object> _canExecute;
protected Func<object, Task> _asyncExecute;

public AsyncDelegateCommand(Func<object, Task> execute)
    : this(execute, null)
{
}

public AsyncDelegateCommand(Func<object, Task> asyncExecute,
			   Predicate<object> canExecute)
{
    _asyncExecute = asyncExecute;
    _canExecute = canExecute;
}

So creating an instance of the AsyncDelegateCommand class using the first constructor (without controlling command availability with the canExecute predicate) looks like this:

var cmd = new AsyncDelegateCommand(
              async _ =>
              {
                  await ...;
              });

We simply pass in an async lambda instead of a synchronous one – that’s all. It’s that simple. The rest is taken care of by the implementation of AsyncDelegateCommand.

Now let’s assume we want to do some pre- and post-processing around the asynchronous call. Whatever it is, it will run synchronously (since only a call to await …; will turn the call into a concurrent call – except you put in other concurrent calls, of course)

var cmd = new AsyncDelegateCommand(
              async _ =>
              {
                  pre();
                  await ...;
                  post();
              });

It reads like what it does. The only difference within our view models (to come back to the motivation of this post) is the use of the new async & await keywords. Amazing, isn’t it? We don’t need callbacks, we don’t need explicit pre- and post-processing methods, we can just write it down as we’d expect.

Finally let’s have a look at the complete code of the AsyncDelegateCommand class:

public class AsyncDelegateCommand : ICommand
{
	protected readonly Predicate<object> _canExecute;
	protected Func<object, Task> _asyncExecute;

	public event EventHandler CanExecuteChanged
	{
		add { CommandManager.RequerySuggested += value; }
		remove { CommandManager.RequerySuggested -= value; }
	}

	public AsyncDelegateCommand(Func<object, Task> execute)
		: this(execute, null)
	{
	}

	public AsyncDelegateCommand(Func<object, Task> asyncExecute,
				   Predicate<object> canExecute)
	{
		_asyncExecute = asyncExecute;
		_canExecute = canExecute;
	}

	public bool CanExecute(object parameter)
	{
		if (_canExecute == null)
		{
			return true;
		}

		return _canExecute(parameter);
	}

	public async void Execute(object parameter)
	{
		await ExecuteAsync(parameter);
	}

	protected virtual async Task ExecuteAsync(object parameter)
	{
		await _asyncExecute(parameter);
	}
}

It’s just a little bit more work to turn this into a generic version taking any type of parameter instead of object. It should be no problem for you to implement this, I never came across a situation where I actually needed a command parameter. If you do, just go ahead and spend the time to improve the implementation. Feel free to post your improvements, I am always happy to learn from other people’s code. Hope you find this one useful. I appreciate your feedback…

UPDATE:

Brent was so kind to share his generic solution down in the comments section. I put it here for easier access.

public class AsyncDelegateCommand<TArgType> : IAsyncCommand
{
  protected readonly Predicate _canExecute;
  protected Func _asyncExecute;

  public event EventHandler CanExecuteChanged
  {
      add { CommandManager.RequerySuggested += value; }
      remove { CommandManager.RequerySuggested -= value; }
  }

  public AsyncDelegateCommand(Func asyncExecute, Predicate canExecute = null)
  {
    _asyncExecute = asyncExecute;
    _canExecute = canExecute;
  }

  public bool CanExecute(object parameter)
  {
    if(_canExecute == null)
    {
      return true;
    }

    return _canExecute((TArgType)parameter);
  }

  public async void Execute(object parameter)
  {
    await AsyncRunner(parameter);
  }

  public async Task ExecuteAsync(object parameter)
  {
    await AsyncRunner(parameter);
  }

  protected virtual async Task AsyncRunner(object parameter)
  {
    await _asyncExecute((TArgType)parameter);
  }
}


public interface IAsyncCommand : ICommand
{
  Task ExecuteAsync(object parameter);
}

18 thoughts on “MVVM AsyncDelegateCommand – what async/await can do for UI development

  1. I just started looking into async and await. I may figure it out before you respond, but what does the ViewModel side look like?

    1. Hi Jared,

      sorry for being late. You can use it within your view models in exactly the same way you are using a synchronous DelegateCommand implementation.
      A simple example for a ViewModel might look like this:


      public class MyViewModel : INotifyPropertyChanged
      {
      private readonly ICommand _someCommand;

      public MyViewModel()
      {
      _someCommand = new AsyncDelegateCommand(
      async _ =>
      {
      pre();
      await ...;
      post();
      });
      }

      public ICommand SomeCommand
      {
      get { return _someCommand; }
      }
      }

      You could now e.g. bind a button’s Command dependency property to the command of this view model. Nothing special to care about, using it is really no different compared to conventional DelegateCommand implementations.

  2. Hi,
    Thanks for a very useful post. I am interested how to unit test this Async Commands though. Can you give me an example as I was hoping in my unit test I can simply do “await CommandName.Execute(object)”. But that is not the case.

    Jeff

    1. Hi Jeff,

      unit testing the commands could be done in several ways.

      1. If you can isolate the code that is executed by the command and test this code on its own, you won’t even have to test async code.
      2. If you cannot isolate the code or just want to test it all at once, you would (at my first sight) have to change the ExecuteAsync(..) methods visibility to public (instead of protected) and then use xUnit, mstest or any other unit testing framework supporting test methods carrying the async modifier to write tests that call the ExecuteAsync method.

      This are just some quick thoughts of mine that may lead you in the right direction. If I find the time, I’ll write a new post regarding the testability of the async delegate command. Thanks for pointing me into this direction.

  3. hello,

    I keep reading that async void is not a good thing as it hides unhandled exceptions that happens inside the methods, so wouldn’t this implementaton suffer from this problem? Like, if an exception happned inside ExecuteAsync wouldn’t it be lost and you wouldn’t know about it?

    Thank you very much!

    1. Eric, thanks for sharing your thoughts. I agree with you, that ‘async void‘ has its problems. It was mainly added to support the old-style event handler signatures which have this ‘void(object, EventArgs)‘ signature. Since the ICommand interface demands an Execute-method with a void-return type, we have no other chance than to accept it.
      So I think, there is two different usage scenarios we must consider.

      The first (and most likely usage scenario) is, when you use the command together with a binding. In this case, unhandled exceptions would fall through up to the binding layer. That’s not what I’d like to see. instead, I implement exception handling within the command’s Execute method itself. Maybe I can silently recover without annoying the user, maybe I must just log the error or maybe I have to inform the user. Whatever the case, it is safe to handle the exception from within the command itself.

      The second (less likely usage scenario) is, when you directly call the Execute method on the command. This is the case were your concerns get real. To cleanly come around this situation, I would suggest to change the visibility modifier from the ExecuteAsync method from protected to public. You could then call the ExecuteAsync method and have a Task returned.

      What do you think about that?

      1. Sounds good to me! Specially if I don’t lose unhandled exceptions!
        I just want to know what is CommandManager.RequerySuggested:

        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }

        I can’t add this reference on Windows Phone 8…

        Thank you!

        1. Hi Eric, sorry for being late. The CommandManager.RequerySuggested thing in the CanExecuteChanged-Event is there, to notify consumers of the command about changes in the command’s CanExecute() conditions. One could raise that manually (as implemented in PRISMs DelegateCommand.RaiseCanExecuteChanged() method), but as long as I have no performance issues I would go with the approach I took in this post, as you don’t have to care about thinking whether the CanExecute() of your command is influenced. So, as long as WP8 does not support this, you could happily go without it 😉

      2. I tested here and it seems to be working perfectly!
        I had to get rid of the CommandManager.RequerySuggested, but it worked!
        Thank you very much!

  4. I’ve tried several now, and this is the best async command implementation I’ve seen yet, as the canExecute function is working as expected. Nice work!

  5. Here’s my modified, generic version. I added an ExecuteAsync() method so that calling code other than UI bindings can actually await on it properly.


    public class AsyncDelegateCommand : IAsyncCommand
    {
    protected readonly Predicate _canExecute;
    protected Func _asyncExecute;

    public event EventHandler CanExecuteChanged
    {
    add { CommandManager.RequerySuggested += value; }
    remove { CommandManager.RequerySuggested -= value; }
    }

    public AsyncDelegateCommand(Func asyncExecute,
    Predicate canExecute = null)
    {
    _asyncExecute = asyncExecute;
    _canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
    if(_canExecute == null)
    {
    return true;
    }

    return _canExecute((TArgType)parameter);
    }

    public async void Execute(object parameter)
    {
    await AsyncRunner(parameter);
    }

    public async Task ExecuteAsync(object parameter)
    {
    await AsyncRunner(parameter);
    }

    protected virtual async Task AsyncRunner(object parameter)
    {
    await _asyncExecute((TArgType)parameter);
    }
    }

    …where IAsyncCommand is:


    public interface IAsyncCommand : ICommand
    {
    Task ExecuteAsync(object parameter);
    }

    Thanks for the example!

    1. Hi Brent, thanks for posting your generic solution. I’ll update the original post and add your solution, so others don’t have to dig the comments for it.

Leave a Reply

Your email address will not be published. Required fields are marked *