我试图通过在任务中调用 CancellationTokenSource.Cancel() 方法来取消任务<>,但我无法让它工作。
这是我使用的代码:
TaskScheduler ts = TaskScheduler.Current;
CancellationTokenSource cts = new CancellationTokenSource();
Task t = new Task( () =>
{
Console.WriteLine( "In Task" );
cts.Cancel();
}, cts.Token );
Task c1 = t.ContinueWith( antecedent =>
{
Console.WriteLine( "In ContinueWith 1" );
}, CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, ts );
Task c2 = c1.ContinueWith( antecedent =>
{
Console.WriteLine( "In ContinueWith 2" );
}, TaskContinuationOptions.NotOnCanceled );
t.Start();
Console.ReadKey();
Environment.Exit( 1 );
此打印输出:
In Task
In ContinueWith 1
In ContinueWith 2
我的预期是这样的:
In Task
我是不是漏掉了什么?只能在任务的之外取消任务吗?
最佳答案
只有在以下情况下任务才被视为“已取消”
- 它的取消标记在开始执行之前被取消。
- 它的取消 token 在执行时被取消,代码通过抛出 OperationCancelledException 协同观察取消(通常通过代码调用
cts.Token.ThrowIfCancellationRequested()
)
如果您在 cts.Cancel()
之后添加了 cts.Token.ThrowIfCancellationRequested()
行,那么事情就会如您所愿。在您的示例中,取消发生在任务运行时,但任务没有观察到取消,并且任务的操作一直运行到完成。因此任务被标记为“运行到完成”。
您可以通过检查延续中的取消 token (cts.Token.IsCancellationRequested
)。有时有帮助的另一种选择是使用原始取消 token 作为继续的取消 token (这样,如果先前任务没有注意到取消,它至少会受到继续的尊重)——因为 TPL甚至在它有机会运行之前将继续标记为已取消。
关于c# - 取消任务中的任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13344340/