Search code examples
xamarin.androidmvvmcross

How to cancel IMvxAsyncCommand?


I just started using xamarin android with MVVMcross platform. I need to cancel an IMvxAsyncCommand but I try a lot of way, it still not work. Does anyone have any ideas or sample of this?


Solution

  • You can actually cancel a MvxAsyncCommand directly without creating any additional CancellationTokenSource.

    Just call Cancel() on the object itself.

    So instead of having the property being ICommand or IMvxCommand use MvxAsyncCommand or IMvxAsyncCommand.

    This way when you have a CancellationToken as argument in your Task and you call Cancel() on the command, it will cancel that token.

    private async Task MyAsyncStuff(CancellationToken ct)
    {
        await abc.AwesomeAsyncMethod(ct);
        // and/or
        ct.ThrowIfCancellationRequested();
    }
    

    So if you modify @fmaccaroni's answer, you will get this:

    public class MyClass
    {    
        public MyClass()
        {
            MyAsyncCommand = new MvxAsyncCommand(MyAsyncStuff);
            CancelMyTaskCommand = new MvxCommand(() => MyAsyncCommand.Cancel());
        }
    
        public IMvxAsyncCommand MyAsyncCommand {get; private set; }
    
        public ICommand CancelMyTaskCommand { get; private set; }
    
        private async Task MyAsyncStuff(CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
    
            await foo.BlablaAsync();
    
            cancellationToken.ThrowIfCancellationRequested();
    
            await bar.WhateverAsync();
    
            cancellationToken.ThrowIfCancellationRequested();
    
            await foo2.AnotherAsync();
        }
    }
    

    EDIT: or even better if your async methods also allow passing along the CancellationToken cancelling them directly, the MyAsyncStuff method could be written like:

    private async Task MyAsyncStuff(CancellationToken cancellationToken)
    {
        await foo.BlablaAsync(cancellationToken);
        await bar.WhateverAsync(cancellationToken);
        await foo2.AnotherAsync(cancellationToken);
    }
    

    Or if you don't care which order they get started and complete in:

    private Task MyAsyncStuff(CancellationToken cancellationToken)
    {
        return Task.WhenAll(
            foo.BlablaAsync(cancellationToken),
            bar.WhateverAsync(cancellationToken),
            foo2.AnotherAsync(cancellationToken));
    }