is asynchronous version of relaycommand required in order to run async methods correctly

Coding Dude

I have the following code defined in a viewmodel. I think that the SaveAsync of type Func<Task> is getting converted to Action since RelayCommand takes an Action not a Func<Task> but I'm not clear on the implications of that.

1) Does RelayCommand need to be replaced with an asynchronous version (RelayCommandAsync)? 2) What exactly is the current code doing regarding asynchrony? 3) What if anything could/should I change to improve/correct it?

private ICommand _saveCommand;
public ICommand SaveCommand
{
    get { return _saveCommand ?? (_saveCommand = new RelayCommand(async () => await SaveAsync(), CanSave)); }
}

public bool CanSave()
{
    return !IsBusy;
}

private async Task SaveAsync()
{
    IsBusy = true;

    try
    {
        await _service.SaveAsync(SomeProperty); 
    }
    catch ( ServiceException ex )
    {
        Message = "Oops. " + ex.ToString();
    }
    finally
    {
        IsBusy = false;
    }
}

Thanks!

EDIT: After some experimenting it does appear that the async method itself works as it should. And it did not make a difference whether async/await was included in the lambda nor whether the method was defined as async Task or async void.

However, what does not work correctly is the canExecute predicate functionality that automatically enables/disables the control binding to the command. What happens is that the button is correctly disabled while the async method runs but it is not enabled afterwards. I have to click somewhere on the window once and then it becomes enabled again.

So it appears an async version of RelayCommand is required for full functionality, i.e. so canExecute can do its thing correctly.

Stephen Cleary

1) Does RelayCommand need to be replaced with an asynchronous version (RelayCommandAsync)?

It doesn't have to be, but you should consider it.

2) What exactly is the current code doing regarding asynchrony?

It's creating an async void lambda. This is problematic because async void does not handle exceptions particularly nicely. If you do use RelayCommand with asynchronous code, then you'll definitely want to use a try/catch like the one in your code.

3) What if anything could/should I change to improve/correct it?

If this is the only async command in your code, I'd say it's fine. However, if you find that you have several async commands in your application with similar semantics, then you should consider writing a RelayCommandAsync.

There is no standard pattern (yet); I outline a few different approaches in an MSDN article. Personally, at the very least I define an IAsyncCommand in my applications, which I expose from my VMs (it's difficult to unit test an async ICommand).

However, what does not work correctly is the canExecute predicate functionality that automatically enables/disables the control binding to the command.

Assuming that RelayCommand.CanExecuteChanged is delegating to CommandManager, then you can just call CommandManager.InvalidateRequerySuggested after setting IsBusy.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Run asynchronous methods in Catalyst Perl

From Dev

Using async to run multiple methods

From Dev

Where do async methods run?

From Dev

How to correctly write Parallel.For with async methods

From Dev

Run Asynchronous Tasks in Order using AA?

From Dev

Always use the 'async' and 'await' keywords in asynchronous methods in a library?

From Dev

What is my mistake in implementing an asynchronous RelayCommand?

From Dev

How to run async in consecutive order in angular

From Dev

How to run test methods in order with Junit

From Dev

JUnit run the methods in the same order as in file

From Dev

JUnit run the methods in the same order as in file

From Dev

How do I run asynchronous functions in order in Angular?

From Dev

How to unit test RelayCommand that Executes an async method?

From Dev

Running an async method inside a relaycommand using MVVM

From Dev

How to determine the minimal required .NET framework version to run my app

From Dev

What's the minimal compatible Linux kernel version required to run Ubuntu?

From Dev

What's the minimal compatible Linux kernel version required to run Ubuntu?

From Dev

How to run async methods inside OnElementChanged method in a custom renderer

From Dev

How to get C# async methods to actually run in parallel?

From Dev

iOS Singleton API manager with dispatch_async/asynchronous methods: what's the implication?

From Dev

Async and Await Task - on which methods to make asynchronous in N-Tier application?

From Dev

io_service::run() processing order of async_* functions

From Dev

Run a bunch async tasks when a certain execution order needs to be preserved

From Dev

How to run testNG methods from different classes in Sequential order

From Dev

Don't understand output order of thread constructor, start and run methods

From Dev

Don't understand output order of thread constructor, start and run methods

From Dev

@Async not asynchronous in Groovy

From Dev

Asynchronous methods not running in parallel

From Dev

Asynchronous methods in using statement

Related Related

  1. 1

    Run asynchronous methods in Catalyst Perl

  2. 2

    Using async to run multiple methods

  3. 3

    Where do async methods run?

  4. 4

    How to correctly write Parallel.For with async methods

  5. 5

    Run Asynchronous Tasks in Order using AA?

  6. 6

    Always use the 'async' and 'await' keywords in asynchronous methods in a library?

  7. 7

    What is my mistake in implementing an asynchronous RelayCommand?

  8. 8

    How to run async in consecutive order in angular

  9. 9

    How to run test methods in order with Junit

  10. 10

    JUnit run the methods in the same order as in file

  11. 11

    JUnit run the methods in the same order as in file

  12. 12

    How do I run asynchronous functions in order in Angular?

  13. 13

    How to unit test RelayCommand that Executes an async method?

  14. 14

    Running an async method inside a relaycommand using MVVM

  15. 15

    How to determine the minimal required .NET framework version to run my app

  16. 16

    What's the minimal compatible Linux kernel version required to run Ubuntu?

  17. 17

    What's the minimal compatible Linux kernel version required to run Ubuntu?

  18. 18

    How to run async methods inside OnElementChanged method in a custom renderer

  19. 19

    How to get C# async methods to actually run in parallel?

  20. 20

    iOS Singleton API manager with dispatch_async/asynchronous methods: what's the implication?

  21. 21

    Async and Await Task - on which methods to make asynchronous in N-Tier application?

  22. 22

    io_service::run() processing order of async_* functions

  23. 23

    Run a bunch async tasks when a certain execution order needs to be preserved

  24. 24

    How to run testNG methods from different classes in Sequential order

  25. 25

    Don't understand output order of thread constructor, start and run methods

  26. 26

    Don't understand output order of thread constructor, start and run methods

  27. 27

    @Async not asynchronous in Groovy

  28. 28

    Asynchronous methods not running in parallel

  29. 29

    Asynchronous methods in using statement

HotTag

Archive