【问题标题】:Task is cancelled only when ThrowIfCancellationRequested is called仅在调用 ThrowIfCancellationRequested 时取消任务
【发布时间】:2021-12-14 23:27:31
【问题描述】:

我有一个正在执行无限循环的任务。

我有一个 CancellationToken,我将它传递给 Task.Run 调用,作为实际的 ExecutePoll 函数。

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

当任务被取消时,应该运行一个 Continuation。

事实证明,只有当我明确调用 cancellationToken.ThrowIfCancellationRequested(); 时才会运行此延续。如果我只跳出循环,则任务始终处于以下状态: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);
            }
        }
    }
}

【问题讨论】:

标签: c# .net-core async-await task-parallel-library


【解决方案1】:

没有错,很好解释here

您可以使用以下选项之一终止操作:

  • 通过简单地从代理返回。在许多情况下,这已经足够了; 但是,以这种方式取消的任务实例 转换到 TaskStatus.RanToCompletion 状态,而不是 TaskStatus.Canceled 状态。

  • 通过抛出 OperationCanceledException 并将请求取消的令牌传递给它。这样做的首选方法是 使用 ThrowIfCancellationRequested 方法。一个任务是 以这种方式取消转换到 Canceled 状态,该状态 调用代码可以用来验证任务是否响应了它的 取消请求。

【讨论】:

    猜你喜欢
    • 2017-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-07
    • 1970-01-01
    相关资源
    最近更新 更多