只有在调用 ThrowIfCancellationRequested 时才会取消任务

Task is cancelled only when ThrowIfCancellationRequested is called

我有一个无限循环的任务。

我有一个 CancellationToken,我将其传递给关于实际 ExecutePoll 函数的 Task.Run 调用。

我等了几秒钟然后取消令牌。

取消任务时应该 运行 有一个继续。

如果我显式调用 cancellationToken.ThrowIfCancellationRequested();,那么这个延续只有 运行s。如果我只是跳出循环,任务总是处于状态:RanToCompletion

任何人都可以分享一些关于我在这里出错的信息吗?

代码:

using System.Threading;
using System.Threading.Tasks;

namespace TaskCancellationTest
{
    class Program
    {
        private static CancellationTokenSource _pollProcessTokenSource;

        static async Task Main(string[] args)
        {
            InitPollingProcess();

            await Task.Delay(5000);

            Console.WriteLine("Cancelling loop");
            _pollProcessTokenSource.Cancel();
            Console.WriteLine("Loop cancelled");

            Console.ReadLine();
        }

        private static void InitPollingProcess()
        {
            try
            {
                _pollProcessTokenSource = new CancellationTokenSource();

                Task pollForListenerConfigs = Task.Run(async () =>
                {
                    await ExecutePoll(_pollProcessTokenSource.Token);
                },
                    _pollProcessTokenSource.Token);

                pollForListenerConfigs.ContinueWith(_ =>
                {
                    Console.WriteLine("Poll process stopped!");
                }, TaskContinuationOptions.OnlyOnCanceled);

                pollForListenerConfigs.ContinueWith(t =>
                {
                    Console.WriteLine($"Task status: {t.Status}");
                });
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Poll process failed with Exception:\n {ex.Message}");
            }
        }

        private static async Task ExecutePoll(CancellationToken cancellationToken)
        {
            while (true)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    Console.WriteLine("Exit from poll loop!");
                    //cancellationToken.ThrowIfCancellationRequested(); // UNCOMMENT TO MAKE CONTINUATION RUN
                    break;
                }

                Console.WriteLine("Looping...");

                await Task.Delay(1000);
            }
        }
    }
}

没有错,解释的很好here:

You can terminate the operation by using one of these options:

  • By simply returning from the delegate. In many scenarios this is sufficient; however, a task instance that is canceled in this way transitions to the TaskStatus.RanToCompletion state, not to the TaskStatus.Canceled state.

  • By throwing a OperationCanceledException and passing it the token on which cancellation was requested. The preferred way to do this is to use the ThrowIfCancellationRequested method. A task that is canceled in this way transitions to the Canceled state, which the calling code can use to verify that the task responded to its cancellation request.