取消任务中的任务

时间:2012-11-12 13:11:34

标签: 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

我在这里遗漏了什么吗?任务只能在任务 之外被取消吗?

2 个答案:

答案 0 :(得分:7)

如果

,任务仅被视为“已取消”
  • 取消令牌在开始执行之前被取消
  • 取消令牌在执行时被取消,代码通过抛出OperationCancelledException(通常是调用cts.Token.ThrowIfCancellationRequested()的代码)协同观察取消,

如果您在cts.Token.ThrowIfCancellationRequested()之后添加了cts.Cancel()行,那么事情的行为就像您期望的那样。在您的示例中,取消发生在任务运行时,但任务不会观察到取消,并且任务的操作将运行完成。因此任务标记为“完成任务”。

您可以通过检查延续(cts.Token.IsCancellationRequested)内的取消令牌来检查“完成任务”但已取消(在任务完成期间或之后)的任务的情况。有时帮助的另一个选项是使用原始取消令牌作为延续的取消令牌(这样,如果先前任务没有注意到取消,它至少会被延续所尊重) - 因为TPL将继续作为取消标记,甚至有机会运行。

答案 1 :(得分:0)

此代码段按预期工作。

var cts = new CancellationTokenSource();

            var t = new Task(() =>
            {
                Console.WriteLine("In Task");
                cts.Cancel();
            }, cts.Token);

            Task c1 = t.ContinueWith(antecedent =>
            {
                Console.WriteLine("In ContinueWith 1");
            }, CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled/* by definition from MSDN here must be NotOnCanceled*/, TaskScheduler.Current);

            c1.ContinueWith(antecedent =>
            {
                Console.WriteLine("In ContinueWith 2");
            }, TaskContinuationOptions.NotOnCanceled);

            t.Start();
            Console.ReadKey();

            Environment.Exit(1);

但似乎TaskContinuationOptions枚举中存在错误。

  

NotOnCanceled指定不应该继续任务   预定如果其前身被取消。此选项无效   多任务延续。

     

OnlyOnCanceled指定延续任务应该是   只有在其前身被取消时才安排。此选项不是   对多任务延续有效。