第三方物流的任务;t检查它是否';s已取消,仍将取消

本文关键字:取消 任务 第三方 检查 是否 | 更新日期: 2023-09-27 17:59:49

我认为CancellationToken/CancellationTokenSource系统的工作方式有点像C++volatile bool bFlagCancelled,这意味着任务的取消是自愿的,它依赖于任务本身来不时检查它是否被取消并抛出异常,无论是显式的还是通过调用ThrowIfCancellationRequested()

但是,如果在StartNew()之后立即调用Cancel,则任务将停止,并且调用Wait()将抛出一个TaskCanceledException

例如,对于此代码:

CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token = source.Token;
Task task = Task.Factory.StartNew(
    () =>
    {
        Console.WriteLine("start sleep");
        Thread.Sleep(1000);
        Console.WriteLine("sleep ended");
    }
    , token);
// Thread.Sleep(1);
source.Cancel();
Console.WriteLine("start wait");
task.Wait();
Console.WriteLine("wait ended");

我得到这个输出:

开始等待异常:System.AggregateException:出现一个或多个错误。--->System.Threading.Tasks.TaskCanceledException:任务已取消

但是,如果我取消对// Thread.Sleep(1);的注释,那么行为就会发生变化,我会得到以下输出:

开始睡眠开始等待睡眠结束等待结束

现在我想这可能是因为task.Start()还没有被调用,但据我所知,StartNew()在返回之前会调用task.Start()——这就是为什么它没有同步成本,建议与创建new Task并自己调用task.Start()相比。

因此,这意味着在某些情况下,即使不检查取消令牌,任务也会自动取消。这是唯一发生这种情况的情况,还是有更多的情况发生这种情况?

第三方物流的任务;t检查它是否';s已取消,仍将取消

Task.Factory.StartNew在返回之前安排任务,但这并不意味着任务实际上已经开始执行。因此,如果TaskScheduler接受该任务,则仍有取消该任务的空间(内部调用TaskScheduler.TryDequeue方法。如果返回true,则该任务可以标记为已取消)。