c# - 取消任务中的任务

标签 c# task-parallel-library task

我试图通过在任务中调用 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/

相关文章:

c# - 在 C# cmdlet 中创建 PowerShell PSObject

node.js - 从 C# 调用 Edge.js 时,如何 Hook stdout 和 stderr?

c# - GetAwaiter()。GetResult()和.Result都不对我有用,但是Task.Run(await()=> nameOfMethodTobeCalled())。Result可以工作。我听不懂

c# - 接收集合并为每个元素调用其链接 block 的 TPL 数据流

c# - 等待任务结果时会发生什么?

android - 如何知道我的应用程序是在前台还是后台,android?

c# - 如何在 .NET Core 中查找字体和字符串指标?

c# - 在将 botauth 与 Azure 表存储结合使用时,登录的用户上下文也在新对话中使用

c# - 以线程安全的方式使用增量编号更新文件

c# - HttpClient Parallel Requests Timeout using Task.WhenAll 当一个请求超时