TPL任务是否可以检查是否已取消,仍然可以取消?

时间:2016-08-02 12:45:09

标签: c# task-parallel-library cancellation cancellationtokensource cancellation-token

我认为CancellationToken / CancellationTokenSource系统有点像C ++ volatile bool bFlagCancelled,这意味着取消是任务的自愿,并依赖于任务本身不时检查它是否是取消并明确或通过调用ThrowIfCancellationRequested()抛出异常。

但如果我在StartNew()之后立即致电取消,则任务停止,并且调用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");

我得到了这个输出:

start wait
Exception: System.AggregateException: One or more errors occurred. ---> System.Threading.Tasks.TaskCanceledException: A task was canceled.

但如果我取消注释// Thread.Sleep(1);,那么行为会改变,我会得到这个输出:

start sleep
start wait
sleep ended
wait ended

现在我想也许这是因为task.Start()还没有被调用,但据我所知,StartNew()在返回之前调用了task.Start() - 那个'为什么它没有同步成本,建议与创建new Task并自己调用task.Start()

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

1 个答案:

答案 0 :(得分:1)

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

相关问题