为什么在CancellationTokenSource调用cancel之后,任务的状态不会更改为取消

时间:2015-04-28 05:28:12

标签: c# .net

我做了一个计算数字的任务,任务将在5秒后收到取消请求,但是在任务取消后我检查了任务的状态。任务状态仍在运行。为什么?示例代码如下:

  var cts = new CancellationTokenSource();
        cts.CancelAfter(5000);//Request Cancel after 5 seconds
        var newTask = Task.Factory.StartNew(state =>
        {
            try
            {
                int i = 1;
                var token = (System.Threading.CancellationToken)state;
                while (true)
                {
                    Console.WriteLine(i);
                    i++;
                    Thread.Sleep(1000);
                    token.ThrowIfCancellationRequested();
                }

            }
            catch
            {

            }
            finally
            {
            }


        }, cts.Token, cts.Token);


        try
        {
            newTask.Wait(10000, cts.Token);

        }
        catch
        {
            Console.WriteLine("Catch:"+ newTask.Status);//The status is Running
        }
        Console.ReadLine();

2 个答案:

答案 0 :(得分:3)

该代码存在两个问题:

  1. token.ThrowIfCancellationRequested()完全按照名称所说,它会引发异常。由于您使用try/catch块来捕获它,因此您也可以从任务中返回。 "取消后的任务状态"不会成为Faulted因为框架没有看到异常。
  2. 您正在使用Wait使用相同的取消令牌。这意味着一旦完成5秒,Wait将被取消,并且将执行catch块。此时任务可能会取消也可能不会取消。
  3. 您应该做的是摆脱任务正文中的try/catch/finally,并从致电WaitnewTask.Wait(10000)中移除令牌。

    完整代码:

    var cts = new CancellationTokenSource();
    cts.CancelAfter(5000);//Request Cancel after 5 seconds
    var newTask = Task.Factory.StartNew(state =>
    {
        int i = 1;
        var token = (System.Threading.CancellationToken)state;
        while (true)
        {
            Console.WriteLine(i);
            i++;
            Thread.Sleep(1000);
            token.ThrowIfCancellationRequested();
        }
    }, cts.Token, cts.Token);
    
    try
    {
        newTask.Wait(10000);
    }
    catch
    {
        Console.WriteLine("Catch:"+ newTask.Status);
    }
    

    LINQpad输出:

      

    1
      2
      3
      4
      5
      捉:取消

答案 1 :(得分:0)

尝试将状态打印到catch块之外的控制台。在您打印状态时,CancellationPended和Exception抛出,但状态在catch块执行完成后立即更改。