0

I have async method like this in my View Model

public async Task Download()
{
//Do some background thread to do heavywork and recursive task
await Download();
}

Then I call it my view like this

private async Task LoadData()
{
_vm.Download();
//Do other background task
await _vm.DoElse();
}

and call it like this

Task.Factory.StartNew(async()=> {await LoadData();});

Now my question is how I can cancel Download()?

albilaga
  • 419
  • 1
  • 10
  • 26
  • 1
    Shouldn't it be `await _vm.Download();`? Does your code even work correctly? Because `_vb.DoElse` would be called immediately if I'm not mistaken. – Jens Sep 28 '15 at 10:27
  • 1
    Cancellation Token is what you need. Example can be found [here](http://blogs.msdn.com/b/csharpfaq/archive/2010/07/19/parallel-programming-task-cancellation.aspx). And yes, current `_vm.Download();` is blocking your thread so you won't be able to cancel. – xZ6a33YaYEfmv Sep 28 '15 at 10:31

1 Answers1

0

You should pass to async method CancellationToken.

Then you should check it on every iteration:

public async Task Download(CancellationToken cancellationToken)
{
    if (cancellationToken.IsCancellationRequested)
    {
        //Do work on cancel
        return;
    }
    //Do some background thread to do heavywork and recursive task
    await Download();
}

To cancel it outside you should handle somewhere outside CancellationTokenSource object, and when you want to cancel, just call _cancellationTokenSource.Cancel()

Task.Factory.StartNew(async()=> {await LoadData(_cancellationTokenSource.Token);});

private async Task LoadData(CancellationToken cancellationToken)
{
    await _vm.Download(cancellationToken);
    //Do other background task
    await _vm.DoElse(cancellationToken);
}
Kirill Bestemyanov
  • 11,946
  • 2
  • 24
  • 38
  • 3
    Yes, use `CancellationToken`, but no, don't check `IsCancellationRequested` and then return normally. Use `cancellationToken.ThrowIfCancellationRequested()` instead. This uses an exception, causing higher-up callers to automatically cancel as well unless they specifically choose to handle the cancellation differently, and clearly indicates to the caller that the task hasn't completed normally. –  Sep 28 '15 at 10:38
  • Are you not supposed to `token.ThrowIfCancellationRequested();` instead of return inside the `if (cancellationToken.IsCancellationRequested)`? – Johan Larsson Sep 28 '15 at 10:39
  • It depends on behaviour you need. If you want to catch this exception upper in callstack, you can use token.ThrowIfCancellationRequested(). If it is normal, that task can be silently canceled, this solution is good. In my code i used both cases depends on requirements. – Kirill Bestemyanov Sep 28 '15 at 14:14