Async / await in MVVM without Void methods

I want to use async / await on my Windows 8 MVVM project, and I'm struggling to find a good way to implement my ICommands using this api. I read several articles about the subject, and I came across this from MSDN below, which says I need to avoid asynchronous voids, as it becomes 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 should not use asynchronous voids. If with events.

But the problem is that all the examples that I can find on the Internet use asynchronous voids. These 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 latter is an implementation of ICommand using async / await, but also uses asynchronous voids. I am trying to find a solution for this, so I wrote this implementation of ICommand based on 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 do not feel comfortable with this and any other implementation, because I do not know what is the best and optimal.

Can anyone talk about how I should use it, preferably with MVVM?

+6
source share
1 answer

In this article, I pointed out that ICommand.Execute is actually an event handler, so it will be considered as an exception to the "avoid async void " manual:

To summarize this first guide, you should prefer the async Task to async void ... The exception to this rule is the asynchronous event handlers that void should return. This exception includes methods that are logically event handlers, even if they are not literally event handlers (for example, ICommand.Execute implementations).

As for your implementation of ICommand , it actually introduces a flaw without using async void : the implementation of ICommand.Execute will drop the Task without observing its exceptions. Thus, the implementation will ignore any exceptions thrown by the async delegate.

In contrast, the blog post you are linked to has async void ICommand.Execute , which is await Task , allowing the exception to propagate in the context of UI synchronization. Which - in this case - is the desired behavior, because you get the same behavior when synchronous ICommand.Execute throws an exception.

If you have a penchant, I would like you to try out ICommand or two that I wrote for possible future inclusion in my AsyncEx library . the first one is a simple team, very similar to the one you wrote on the blog. The second option is a much more complete version of the "asynchronous command", including cancellation, progress report, and automatic CanExecute control. I would appreciate any feedback.

+21
source

Source: https://habr.com/ru/post/946227/


All Articles