从任务主体内部取消任务

Posted

技术标签:

【中文标题】从任务主体内部取消任务【英文标题】:Task cancellation from inside the task body 【发布时间】:2014-08-16 10:59:44 【问题描述】:

我阅读了有关取消方法的信息,但根据我的理解,它们都可以从任务外部控制任务,但如果我想从内部取消任务。

例如在这个伪代码中:

Task tasks = new Task(() =>
 
     bool exists = CheckFromDB();
      if (!exists)
         break;

我可以从内部取消任务吗? 我得到的唯一想法是在任务内部触发异常并从外部处理它,但这不是正确的方法。

【问题讨论】:

【参考方案1】:

如果您想真正取消任务(例如,在完成后将Status 属性设置为Canceled),您可以这样做:

var cts = new CancellationTokenSource();
var token = cts.Token;

Task innerCancel = new Task(
    () =>
    
        if (!CheckFromDB())
        
            cts.Cancel();
        
        token.ThrowIfCancellationRequested();
    ,
    token);

当您使用return 时,任务实际上不会取消,而是不会执行return 语句之后的代码,并且任务本身的状态为@987654328 @。


在旁注中,advised 使用 Task.Factory.StartNew 用于 .NET 4,Task.Run 用于 .NET 4.5 而不是构造函数来创建任务。

【讨论】:

这是一种更好的方法。 你应该使用Task.Run而不是new Task来返回一个热任务而不是一个冷任务 @YuvalItzchakov,我同意使用Task.Run 而不是返回一个冷任务,但在这种情况下,为了保持一致性,我决定遵循 OP 编写它的方式。 我认为你应该向 OP 展示正确的路径,而不是坚持不正确的一致性:) 请注意,如果您不需要在任务之外取消,您也可以删除取消令牌并使用throw new OperationCanceledException() 代替cts.Cancel() 以获得类似的效果。【参考方案2】:

任务中的 lambda 表达式代码的行为与任何其他方法中的行为相同。如果你出于某种原因想结束任务,你可以简单地返回:

Task task = Task.Run(() =>
 
    if(!CheckFromDB())
    
        return;
    

您也可以抛出异常。这将结束任务并将其标记为错误,但如果您可以避免它,则没有理由这样做。如果你真的在回应一些你无法克服的问题,那么是的,只要抛出一个异常。

【讨论】:

没有我可以使用或分配的属性,以便我可以处理退货。 @user733659 想知道具体的退货吗?不是真的......但是你可以让 lambda 返回一个值(可能是一个布尔值)。你也可以抛出一个特定的异常。 您可以使用事件或blogs.msdn.com/b/csharpfaq/archive/2010/07/19/…

以上是关于从任务主体内部取消任务的主要内容,如果未能解决你的问题,请参考以下文章

如何从另一个任务中取消 ScheduledFuture 任务并优雅地结束?

如何从客户端取消异步任务

上QQ任务栏出现ffdshow audio decoder!怎么取消!

Chocolatey 和 powershell:从任务栏和文件关联中固定和取消固定程序

如何取消 useEffect 清理函数中的所有订阅和异步任务?

ExecutorService 的未来任务没有真正取消