.NET CancellationTokenSource 取消任务用法详解

原文: https://docs.microsoft.com/en...

本文对原文进行了提炼并翻译为中文。

Cancel不代表终止代码

不要想当然地依靠Cancel机制“terminate a Task”,这是做不到的!

一个常见的误解是取消了一个任务后,该任务就会自动停止;但其实这种理解是不正确的;试想一下,如果取消真的可以达到terminate一个Task的效果,那它和危险的Thread.Abort有什么区别呢?因为真的按照“cancel即在Task代码内部抛出异常”去理解,那么你没有对结束后的程序状态有任何扫尾工作。

所以CancellationTokenSource抑或其对应的CancellationToken都只是发一个通知给Task:你可以结束了;而具体怎样捕获这个消息并响应,是Task的用户代码自己思考的问题。

参考原文中的代码,关键的一个片段是:

if (ct.IsCancellationRequested)
{
    Console.WriteLine("Task {0} cancelled", taskNum);
    ct.ThrowIfCancellationRequested();
}

这类似于软件工程中的“埋点”,即在关键的代码行中插入监控代码,判断任务是否被取消

WhenAny或Wait(token)会导致异常抛出

看回原文中的代码:

try
{
    await Task.WhenAll(tasks.ToArray());
}
catch (OperationCanceledException)
{
    Console.WriteLine($"\n{nameof(OperationCanceledException)} thrown\n");
}

一旦任务取消,那么Task.WhenAll会导致异常抛出;这里是非常容易误导人的一点:Task内部也发生了异常,从而打断的Task内部代码流,从而令任务强制退出了吗?

答案是:Task本身代码运行只受到自己内部代码控制,不可能单单因为CancellationTokenSource发出了取消信号,就终端了任务的运行。

你可能感兴趣的:(.net)