当任务被取消时,继续任务不会执行

本文关键字:任务 执行 继续 取消 | 更新日期: 2023-09-27 18:21:10

的想法:创建一个打印越来越多星号的Task。当用户按下Enter时,Task会打印10个星号,然后停止。

代码

namespace CancellingLongRunningTasks
{
    using System;
    using System.Threading;
    using System.Threading.Tasks;
    class Program
    {
        static void Main()
        {
            var cancellationTokenSource = new CancellationTokenSource();
            var token = cancellationTokenSource.Token;
            Task task = Task.Run(() =>
            {
                int count = 1;
                while (!token.IsCancellationRequested)
                {
                    Console.WriteLine(new string('*', count));
                    Thread.Sleep(1000);
                    count++;
                }
            }, token).ContinueWith(
                parent =>
                {
                    var count = 10;
                    while (count > 0)
                    {
                        Console.WriteLine(new string('*', count));
                        Thread.Sleep(1000);
                        count--;
                    }
                }, TaskContinuationOptions.OnlyOnCanceled);
            Console.WriteLine("Press enter to stop the task.");
            if (Console.ReadLine().Contains(Environment.NewLine))
            {
                cancellationTokenSource.Cancel();
                task.Wait();
            }
        }
    }
}

问题:为什么我的延续任务没有执行?

当任务被取消时,继续任务不会执行

它没有被执行,因为您没有主动取消Task,只是检查是否请求了取消。使用抛出OperationCanceledException并将Task转换为已取消状态的CancellationToken.ThrowIfCancellationRequested,或者简单地抛出带有相应令牌的异常:

Task task = Task.Run(() =>
{
      int count = 1;
      while (!token.IsCancellationRequested)
      {
           Console.WriteLine(new string('*', count));
           Thread.Sleep(1000);
           count++;
       }
       token.ThrowIfCancellationRequested();
 }, token)

相当于:

Task task = Task.Run(() =>
{
      int count = 1;
      while (!token.IsCancellationRequested)
      {
           Console.WriteLine(new string('*', count));
           Thread.Sleep(1000);
           count++;
       }
       throw new OperationCanceledException(token);
 }, token)