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

Tim*_*imF 5 c# task-parallel-library .net-4.5 xamarin xamarin.forms

我需要取消返回任务的API调用,但它不会将CancellationToken作为参数,我不能添加一个.

我该如何取消该任务?

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

 IEnumerable<Position> positions = await geo.GetPositionsForAddressAsync(address); 
Run Code Online (Sandbox Code Playgroud)

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

我也担心我的应用程序会进入休眠状态,并且没有停止长时间运行的任务,或者任务完成并且需要不再有效的代码.

Sus*_*ver 9

我读到的关于这一点的最好的是来自Stephen Toub的"与.NET并行编程"博客.

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

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; 
}
Run Code Online (Sandbox Code Playgroud)

然后使用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 
}
Run Code Online (Sandbox Code Playgroud)

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

  • 需要明确的是,这并没有取消任务......它取消了对任务的等待,然后排队"清理"动作,无论何时最终完成.整洁的概念,和有趣的博客文章. (2认同)