Skip to main content

AsyncCommand Class

An asynchronous command without a command parameter.

Namespace: DevExpress.Mvvm

Assembly: DevExpress.WinUI.Mvvm.v23.2.dll

NuGet Package: DevExpress.WinUI

Declaration

public class AsyncCommand :
    AsyncCommand<object>

Remarks

You can use asynchronous commands to run a time-consuming operation in a separate thread and keep the UI responsive.

For example, you can bind a button to an asynchronous command. When a user clicks the button, the command is invoked and the button becomes disabled. The rest of the interface does not freeze. When the process is done, the button is enabled.

DevExpress WinUI MVVM - AsyncCommand

Run Demo: AsyncCommand Module in the WinUI MVVM Demo

The DevExpress WinUI MVVM Framework includes the following asynchronous commands:

AsyncCommand<T>
A command whose Execute(T) and CanExecute(T) delegates accept a command parameter of the T type.
AsyncCommand
A command whose Execute and CanExecute delegates do not have a command parameter.

Create and Run Asynchronous Commands

The following code sample creates AsyncCommand and AsyncCommand<T> instances and binds them to the Button.Command property.

<Button Content="..." Command="{x:Bind MyAsyncCommand}"/>
<Button Content="..." Command="{x:Bind MyAsyncCommand}" CommandParameter="..."/>
public MyViewModel() {
    MyAsyncCommand = new AsyncCommand<string>(Calculate, CanCalculate);
}

public AsyncCommand<string> MyAsyncCommand { get; }
async Task Calculate(string parameter) {
    //...
}
bool CanCalculate(string parameter) {
    //...
}

Cancel a Command Execution

Do any of the following to cancel a command’s execution:

  • Call a Cancel method.
  • Call the CancelCommand.

    <Button Content="Calculate" Command="{x:Bind MyAsyncCommand}"/>
    <Button Content="Cancel" Command="{x:Bind MyAsyncCommand.CancelCommand}"/>
    <ProgressBar Value="{x:Bind Progress, Mode=OneWay}"/>
    
  • Pass a CancellationToken to the AsyncCommand constructor and call the CancellationToken.ThrowIfCancellationRequested method.

    public AsyncCommand MyAsyncCommand { get; private set; }
    
    public MyViewModel() {
        MyAsyncCommand = new AsyncCommand(Calculate);
    }
    
    async Task Calculate(CancellationToken cancellationToken) {
        for(int i = 0; i <= 100; i++) {
            cancellationToken.ThrowIfCancellationRequested();
            // ...
        }
    }
    

When a command’s cancellation process is started, the IsCancellationRequested property is set to true. When a command is cancelled, the IsCancellationRequested property is set to false.

Access the UI Thread from the Command

Use the IDispatcherService to access the UI thread during the command execution process.

IDispatcherService DispatcherService => GetUIService<IDispatcherService>();
async Task Calculate() {
    ...
    await DispatcherService.InvokeAsync(() => { ... });

    // Or if you do not need to wait until the command is executed:
    DispatcherService.BeginInvoke(() => { ... });
    ...
}

Simultaneous Command Execution

The AsyncCommand and AsyncCommand<T> classes contain the IsExecuting property. When the command execution is in progress, this property is set to true and the CanExecute(T) method returns false. If CanExecute(T) is false, you can disable a control that is bound to the command until the previous command execution is completed.

Set the AsyncCommand.AllowMultipleExecution constructor parameter to true to allow a user to execute a command multiple times simultaneously. In this case, the AsyncCommand.CanExecute method returns a value based on your CanExecute delegate implementation.

MyAsyncCommand = new AsyncCommand<string>(Calculate, CanCalculate, allowMultipleExecution: true);

Inheritance

See Also