Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to cancel a C# Task without a CancellationToken?

I'm need to cancel an API call that returns a Task, but it doesn't take a CancellationToken as a parameter, and I can't add one.

How can I cancel that Task?

In this particular case, I'm using Xamarin.Forms with the Geocoder object.

 IEnumerable<Position> positions = await geo.GetPositionsForAddressAsync(address); 

That call can sometimes take a very long time. For some of my use cases, the user can just navigate to another screen, and that result of that task is no longer needed.

I also worry about my app going to sleep and not having this long running task stopped, or of the task completing and having need of code which is no longer valid.

like image 238
TimF Avatar asked Sep 02 '15 03:09

TimF


1 Answers

The best that I have read about doing this is from Stephen Toub on the "Parallel Programming with .NET" blog.

Basically you create your own cancellation 'overload':

public static async Task<T> WithCancellation<T>( 
    this Task<T> task, CancellationToken cancellationToken) 
{ 
    var tcs = new TaskCompletionSource<bool>(); 
    using(cancellationToken.Register( 
                s => ((TaskCompletionSource<bool>)s).TrySetResult(true), tcs)) 
        if (task != await Task.WhenAny(task, tcs.Task)) 
            throw new OperationCanceledException(cancellationToken); 
    return await task; 
}

And then use that with a try/catch to call your async function:

try 
{ 
    await op.WithCancellation(token); 
} 
catch(OperationCanceledException) 
{ 
    op.ContinueWith(t => /* handle eventual completion */); 
    … // whatever you want to do in the case of cancellation 
}

Really need to read his blog posting...

like image 111
SushiHangover Avatar answered Oct 01 '22 09:10

SushiHangover