【问题标题】:Is it possible to cancel a C# Task without a CancellationToken?是否可以在没有 CancellationToken 的情况下取消 C# 任务?
【发布时间】:2015-09-02 03:21:41
【问题描述】:

我需要取消一个返回 Task 的 API 调用,但它没有将 CancellationToken 作为参数,我无法添加。

如何取消该任务?

在这种特殊情况下,我将 Xamarin.Forms 与 Geocoder 对象一起使用。

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

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

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

【问题讨论】:

  • 假设我们一直在谈论 .NET 代码,也许你可以在一个孩子AppDomain 中使用它?如果它对小猫行为不端或残忍,你可以Unload()
  • @MickyDuncan 卸载 AppDomain 仍然不是最好的解决方案,如果您使用非托管资源并且由于卸载而没有被释放,直到所有 AppDomain 都被卸载并且该过程才会被释放终止。将其设为一个完全独立的进程并使用某种形式的 IPC 与两者进行通信可能会更好。
  • @ScottChamberlain 我确实说过 “假设我们一直在谈论 .NET 代码”。是的,我喜欢 IPC 方法,感谢 Scott
  • @mickyDuncan 我会考虑使用Marshal.StructureToPtr to serialize a struct .NET 代码执行Marshal.AllocHGlobal,但我明白你的意思。

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


【解决方案1】:

我读到的关于这样做的最好的消息来自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 
}

真的需要看他的博文...

【讨论】:

  • 明确一点,这并没有取消任务......它取消的是任务的等待,然后你排队一个“清理”操作,只要它最终完成。简洁的概念和有趣的博客文章。
  • 这很棒。我也可以扩展它以处理超时。我可以在自己的线程中处理任务的实际结束,然后丢弃数据。谢谢!
【解决方案2】:

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

Cancellation 上的链接讨论了有关如何利用取消令牌的各种模式,但由于您正在处理一个您无法控制的库,因此您无能为力。

【讨论】:

    猜你喜欢
    • 2017-11-16
    • 1970-01-01
    • 1970-01-01
    • 2012-09-09
    • 1970-01-01
    • 1970-01-01
    • 2019-05-21
    • 1970-01-01
    相关资源
    最近更新 更多