I want to use async/await on my windows phone 8 MVVM project and I'm struggling to find a good way to implement my ICommands using this api. I've been reading a few articles about the subject and I bumped into this one from MSDN below, which states that I have to avoid async voids since it gets difficult to catch unhandled exceptions: http://msdn.microsoft.com/en-us/magazine/jj991977.aspx In another question I asked about the subject, someone also said that I shouldn't use async voids. Unless with events.
But the problem is that all examples I can find on the internet use async voids. This two articles I found are examples: http://richnewman.wordpress.com/2012/12/03/tutorial-asynchronous-programming-async-and-await-for-beginners/ and http://blog.mycupof.net/2012/08/23/mvvm-asyncdelegatecommand-what-asyncawait-can-do-for-uidevelopment/
The last one is an implementation of ICommand using async/await, but it also uses async voids. I'm trying to come up with a solution for this, so I wrote this implementation of ICommand based on the RelayCommand:
public delegate Task AsyncAction();
public class RelayCommandAsync : ICommand
{
private AsyncAction _handler;
public RelayCommandAsync(AsyncAction handler)
{
_handler = handler;
}
private bool _isEnabled;
public bool IsEnabled
{
get { return _isEnabled; }
set
{
if (value != _isEnabled)
{
_isEnabled = value;
if (CanExecuteChanged != null)
{
CanExecuteChanged(this, EventArgs.Empty);
}
}
}
}
public bool CanExecute(object parameter)
{
return IsEnabled;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
ExecuteAsync();
}
private Task ExecuteAsync()
{
return _handler();
}
}
And I'm trying to use it like this: in the constructor:
saveCommand = new RelayCommandAsync(SaveSourceAsync);
then:
private async Task SaveSourceAsync()
{
await Task.Run(() => { Save(); });
}
private void Save()
{
// Slow operation
}
The problem is that I'm not feeling comfortable with this and any other implementation as I don't know which is the best and optimal.
Can anyone give some light on how I should use it, preferably with MVVM?
In the referenced article, I did point out that ICommand.Execute
is practically an event handler, so it would be considered an exception from the "avoid async void
" guideline:
To summarize this first guideline, you should prefer async Task to async void... The exception to this guideline is asynchronous event handlers, which must return void. This exception includes methods that are logically event handlers even if they’re not literally event handlers (for example, ICommand.Execute implementations).
Regarding your ICommand
implementation, it actually introduces a flaw by not using async void
: the ICommand.Execute
implementation will discard the Task
without observing its exceptions. So that implementation will ignore any exceptions raised by the async
delegate.
In contrast, the blog post you linked to has an async void ICommand.Execute
which await
s the Task
, allowing the exception to propagate to the UI synchronization context. Which - in this case - is the desired behavior because it's the same behavior you get when a synchronous ICommand.Execute
raises an exception.
If you have the inclination, I'd like you to try out an ICommand
or two that I've written for possible future inclusion in my AsyncEx library. The first one is a simple command very similar to the one in the blog you posted. The second one is a much more complete "asynchronous command" implementation including cancellation, progress reporting, and automatic management of CanExecute
. I'd appreciate any feedback.
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