我认为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()
。
那么这意味着在某些情况下,即使没有检查取消令牌,任务也会自动取消。这是发生这种情况的唯一情况,还是有更多情况会发生这种情况?
答案 0 :(得分:1)
Task.Factory.StartNew
在返回之前调度任务,但这并不意味着任务实际开始执行。因此,如果TaskScheduler
接受该任务,则仍有空间取消该任务(在内部,调用TaskScheduler.TryDequeue
方法。如果任务返回true,则该任务可被标记为已取消。)