What is my error when implementing asynchronous RelayCommand?

I am studying WPF and MVVM at the moment, and I had a problem when I tried to write unit tests for viewmodel, whose commands call methods async. This problem is well described in this question. This question also has a solution: write a new Command class with an additional expected method, which can be expected in unit tests. But since I use MvvmLight, I decided not to write a new class, but instead inherit from the built-in class RelayCommand. However, it seems I do not understand how to do this properly. The following is a simplified example illustrating my problem:

AsyncRelayCommand:

public class AsyncRelayCommand : RelayCommand
{
    private readonly Func<Task> _asyncExecute;

    public AsyncRelayCommand(Func<Task> asyncExecute)
        : base(() => asyncExecute())
    {
        _asyncExecute = asyncExecute;
    }

    public AsyncRelayCommand(Func<Task> asyncExecute, Action execute)
        : base(execute)
    {
        _asyncExecute = asyncExecute;
    }

    public Task ExecuteAsync()
    {
        return _asyncExecute();
    }

    //Overriding Execute like this fixes my problem, but the question remains unanswered.
    //public override void Execute(object parameter)
    //{
    //    _asyncExecute();
    //}
}

My ViewModel (based on MvvmLight MainViewModel by default):

public class MainViewModel : ViewModelBase
{
    private string _welcomeTitle = "Welcome!";

    public string WelcomeTitle
    {
        get
        {
            return _welcomeTitle;
        }

        set
        {
            _welcomeTitle = value;
            RaisePropertyChanged("WelcomeTitle");
        }
    }

    public AsyncRelayCommand Command { get; private set; }
    public MainViewModel(IDataService dataService)
    {
        Command = new AsyncRelayCommand(CommandExecute); //First variant
        Command = new AsyncRelayCommand(CommandExecute, () => CommandExecute()); //Second variant
    }

    private async Task CommandExecute()
    {
        WelcomeTitle = "Command in progress";
        await Task.Delay(1500);
        WelcomeTitle = "Command completed";
    }
}

, First Second , . , . , , , Command , , , .

async await . , , Command -.

P.S.: , RelayCommand. , ICommand , .

+4
1

, , . RelayCommand WeakAction, () Action . , .

, , () => CommandExecute() , , :

[CompilerGenerated]
private void <.ctor>b__0()
{
  this.CommandExecute();
}

, .

, () => asyncExecute() , lambda asyncExecute, :

[CompilerGenerated]
private sealed class <>c__DisplayClass2
{
  public Func<Task> asyncExecute;

  public void <.ctor>b__0()
  {
    this.asyncExecute();
  }
}

Action - <>c__DisplayClass2, . WeakAction , .

, RelayCommand (.. ), () Action :

private readonly Func<Task> _asyncExecute;
private readonly Action _execute;

public AsyncRelayCommand(Func<Task> asyncExecute)
    : this(asyncExecute, () => asyncExecute())
{
}

private AsyncRelayCommand(Func<Task> asyncExecute, Action execute)
    : base(execute)
{
  _asyncExecute = asyncExecute;
  _execute = execute;
}

, async; . , , Messenger.

+15

All Articles