是否可以在没有CancellationToken的情况下取消C#任务?

时间:2015-09-02 03:21:41

标签: c# xamarin task-parallel-library .net-4.5 xamarin.forms

我需要取消返回任务的API调用,但它不会将CancellationToken作为参数,我也无法添加。

如何取消该任务?

在这种特殊情况下,我正在使用带有Geocoder对象的Xamarin.Forms。

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

这个电话有时需要很长时间。对于我的一些用例,用户只需导航到另一个屏幕,就不再需要该任务的结果。

我还担心我的应用程序会暂停,并且没有停止这个长时间运行的任务,或者任务完成并且需要不再有效的代码。

2 个答案:

答案 0 :(得分:8)

我读到的关于这样做的最好的是来自Stephen Toub on the "Parallel Programming with .NET" blog

基本上你创建了自己的取消'重载':

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; 
}

然后使用try / catch来调用异步函数:

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

真的需要阅读他的博客帖子......

答案 1 :(得分:4)

简而言之......不能取消不会尝试观察CancellationToken的c#任务,至少在你所指的上下文中是这样。 (例如,结束应用程序,会这样做)

https://jsfiddle.net/q3hhk17e/12/上的链接讨论了如何利用取消令牌的各种模式,但由于您正在处理您无法控制的库,因此您无法做多少事情。