C# Task 实现任务超时取消、超时取消然后重试 超过重试最大次数就结束。

这篇具有很好参考价值的文章主要介绍了C# Task 实现任务超时取消、超时取消然后重试 超过重试最大次数就结束。。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

任务超时取消 示例

        public static async Task TimeoutCancelTask()
        {
            CancellationTokenSource cts = new CancellationTokenSource();//取消令牌
            Task task = DoAction(cts);//业务异步任务
            double timeoutSeconds = 2;//超时时间 秒
            Task delayTask = Task.Delay(TimeSpan.FromSeconds(timeoutSeconds));//指定一个等待任务 等待到超时时间
            Task completeTask = await Task.WhenAny(task, delayTask);//等待两个任务,任意一个任务执行完成。返回率先完成的任务
            if (completeTask == delayTask)//如果率先完成的是超时等待任务,就说明业务任务执行超时了。
            {
                cts.Cancel();//取消令牌 状态改为取消
                Console.WriteLine("任务已超时取消");
            }
            else
            {
                Console.WriteLine("任务已完成");
            }
        }

        //模拟业务任务
        public static async Task DoAction(CancellationTokenSource cts)
        {
            await Task.Delay(200);
            for (int i = 1; i <= 5; i++)
            {
                if (cts.IsCancellationRequested)//在业务任务每个耗时的操作开始之前判断取消令牌是否已取消
                    break;
                Console.WriteLine(i);
                await Task.Delay(TimeSpan.FromSeconds(1));//模拟业务操作,耗时任务。
            }
        }

封装帮助方法


  public static class TaskExtensions
    {
        /// <summary>
        /// 任务超时取消
        /// </summary>
        /// <param name="func">业务任务(超时要取消任务的话 需要在耗时操作之前 判断cts如果取消就结束方法)</param>
        /// <param name="timeoutSeconds">超时时间 秒</param>
        /// <param name="cts">任务取消令牌</param>
        /// <returns>true执行成功 false超时取消</returns>
        public static async Task<bool> TimeoutCancelAsync(
            Func<CancellationTokenSource, Task> func, double timeoutSeconds, CancellationTokenSource cts)
        {
            Task task = func.Invoke(cts);
            Task delayTask = Task.Delay(TimeSpan.FromSeconds(timeoutSeconds), cts.Token);
            Task completeTask = await Task.WhenAny(task, delayTask);
            if (completeTask == task)
                return true;
            cts.Cancel();
            Console.WriteLine("【TimeoutCancelAsync】任务执行超时已取消。");
            return false;
        }

        /// <summary>
        /// 任务超时取消 (带泛型返回值)
        /// </summary>
        /// <param name="func">业务任务带返回值(超时要取消任务的话 需要在耗时操作之前 判断cts如果取消就结束方法)</param>
        /// <param name="timeoutSeconds">超时时间 秒</param>
        /// <param name="cts">任务取消令牌</param>
        /// <returns>IsSuccess:true执行成功 false超时取消  Result:任务执行成功的结果</returns>
        public static async Task<(bool IsSuccess, T Result)> TimeoutCancelAsync<T>(
            Func<CancellationTokenSource, Task<T>> func, double timeoutSeconds, CancellationTokenSource cts)
        {
            Task<T> task = func.Invoke(cts);
            Task<T> delayTask = Task.Delay(TimeSpan.FromSeconds(timeoutSeconds), cts.Token)
                    .ContinueWith(_ => default(T));
            Task completeTask = await Task.WhenAny<T>(task, delayTask);
            if (completeTask == task)
                return (true, task.Result);
            cts.Cancel();
            Console.WriteLine("【TimeoutCancelAsync】任务执行超时已取消。");
            return (false, delayTask.Result);
        }


        /// <summary>
        /// 任务超时取消 然后重新执行
        /// </summary>
        /// <param name="func">业务任务(超时要取消任务的话 需要在耗时操作之前 判断cts如果取消就结束方法)</param>
        /// <param name="timeoutSeconds">超时时间 秒</param>
        /// <param name="maxRetryCount">最大重试次数</param>
        /// <param name="cts">任务取消令牌</param>
        /// <returns>是否成功</returns>
        public static async Task<bool> TimeoutRetryAsync(
            Func<CancellationTokenSource, Task> func, double timeoutSeconds, int maxRetryCount, CancellationTokenSource cts)
        {
            for (int i = 0; i <= maxRetryCount; i++)
            {
                if (cts.IsCancellationRequested)
                    break;
                if (i > 0)
                    Console.WriteLine($"【TimeoutRetryAsync】任务第{i}次重试开始...");
                CancellationTokenSource currentCts = CancellationTokenSource.CreateLinkedTokenSource(cts.Token);
                Task task = func.Invoke(currentCts);
                Task delayTask = Task.Delay(TimeSpan.FromSeconds(timeoutSeconds), currentCts.Token);
                Task completeTask = await Task.WhenAny(task, delayTask);
                if (completeTask == task)
                {
                    currentCts.Dispose();
                    return true;
                }
                currentCts.Cancel();
                Console.WriteLine("【TimeoutRetryAsync】任务执行超时已取消。");
            }
            return false;
        }

        /// <summary>
        /// 任务超时取消 然后重新执行 (带泛型返回值)
        /// </summary>
        /// <param name="func">业务任务带返回值(超时要取消任务的话 需要在耗时操作之前 判断cts如果取消就结束方法)</param>
        /// <param name="timeoutSeconds">超时时间 秒</param>
        /// <param name="maxRetryCount">最大重试次数</param>
        /// <param name="cts">任务取消令牌</param>
        /// <returns>IsSuccess:是否成功  Result:任务执行成功的结果</returns>
        public static async Task<(bool IsSuccess, T Result)> TimeoutRetryAsync<T>(
            Func<CancellationTokenSource, Task<T>> func, double timeoutSeconds, int maxRetryCount, CancellationTokenSource cts)
        {
            for (int i = 0; i <= maxRetryCount; i++)
            {
                if (cts.IsCancellationRequested)
                    break;
                if (i > 0)
                    Console.WriteLine($"【TimeoutRetryAsync】任务第{i}次重试开始...");
                CancellationTokenSource currentCts = CancellationTokenSource.CreateLinkedTokenSource(cts.Token);
                Task<T> task = func.Invoke(currentCts);
                Task<T> delayTask = Task.Delay(TimeSpan.FromSeconds(timeoutSeconds), currentCts.Token)
                    .ContinueWith(_ => default(T));
                Task completeTask = await Task.WhenAny<T>(task, delayTask);
                if (completeTask == task)
                {
                    currentCts.Dispose();
                    return (true, await task);
                }
                currentCts.Cancel();
                Console.WriteLine("【TimeoutRetryAsync】任务执行超时已取消。");
            }
            return (false, default(T));
        }
    }

测试用例:

        public static async Task Go()
        {
            double timeoutSeconds = 2;//超时时间 秒
            int maxRetryCount = 2;//最大重试次数
            CancellationTokenSource cts = new CancellationTokenSource();
            bool isSuccess = false;
            string result = string.Empty;
            //1.超时取消任务 无返回值
            //isSuccess = await TaskExtensions.TimeoutCancelAsync((cts) => DoActionNoResult(cts), timeoutSeconds, cts);

            //1.超时取消任务 无返回值
            //(isSuccess, result) = await TaskExtensions.TimeoutCancelAsync((cts) => DoActionWithResult(cts), timeoutSeconds, cts);

            //3.超时取消并重试任务 无返回值
            //isSuccess = await TaskExtensions.TimeoutRetryAsync((cts) => DoActionNoResult(cts), timeoutSeconds, maxRetryCount, cts);

            //4.超时取消并重试任务 带返回值任务
            (isSuccess, result) = await TaskExtensions.TimeoutRetryAsync((cts) => DoActionWithResult(cts), timeoutSeconds, maxRetryCount, cts);
            
            if(isSuccess) 
            {
                Console.WriteLine("任务执行成功,结果:" + result);
            }
            else
            {
                Console.WriteLine("任务执行失败!");
            }
            Console.ReadLine();
        }

        public static async Task DoActionNoResult(CancellationTokenSource cts)
        {
            await Task.Delay(200);
            for (int i = 1; i <= 5; i++)
            {
                if (cts.IsCancellationRequested)//在业务任务每个耗时的操作开始之前判断取消令牌是否已取消
                    return;
                Console.WriteLine($"num:{i}");
                await Task.Delay(1000);//模拟业务操作,耗时任务。
            }
        }

        public static async Task<string> DoActionWithResult(CancellationTokenSource cts)
        {
            await Task.Delay(200);
            for (int i = 1; i <= 5; i++)
            {
                if (cts.IsCancellationRequested)//在业务任务每个耗时的操作开始之前判断取消令牌是否已取消
                    return "";
                Console.WriteLine($"num:{i}");
                await Task.Delay(1000);//模拟业务操作,耗时任务。
            }
            return "666";
        }

案例4-1

double timeoutSeconds = 2;//超时时间 秒
int maxRetryCount = 2;//最大重试次数 
//业务方法运行时间为5.3秒左右,会一直超时 重试2次后结束

C# Task 实现任务超时取消、超时取消然后重试 超过重试最大次数就结束。

案例4-2

double timeoutSeconds = 6;//超时时间 秒
int maxRetryCount = 2;//最大重试次数 
//业务方法运行时间为5.3秒左右,不会超时,会执行成功并返回结果

C# Task 实现任务超时取消、超时取消然后重试 超过重试最大次数就结束。

案例4-3

double timeoutSeconds = i+4;//超时时间 秒
int maxRetryCount = 2;//最大重试次数 
//业务方法运行时间为5.3秒左右,将超时时间设置为(当前重试次数+4)。前两次执行会超时,第三次执行成功并返回结果

C# Task 实现任务超时取消、超时取消然后重试 超过重试最大次数就结束。
C# Task 实现任务超时取消、超时取消然后重试 超过重试最大次数就结束。文章来源地址https://www.toymoban.com/news/detail-602465.html

到了这里,关于C# Task 实现任务超时取消、超时取消然后重试 超过重试最大次数就结束。的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 超简单的RabbitMq实现订单超时自动取消

    很简单的实现方法,大家帮忙看看能不能继续完善。 步骤: 添加rabbitmq配置 添加rabbitmq配置类 添加订单生产者 添加订单消费者(修改状态) 1、添加rabbitmq配置 注意一定要开启手动应答,不然可能会报错 2、添加rabbitmq配置类 下面这段代码看着有点繁琐,我解释一下逻辑关系

    2024年02月11日
    浏览(26)
  • 订单超时自动取消的技术方案解析及代码实现

    订单超时自动取消是电商平台中常见的功能之一,例如在淘宝、京东、拼多多等商城下单后,如果在一定的时间内没有付款,那么订单会自动被取消,是怎么做到的呢?作为技术人员我们应该了解自动取消的原理和实现逻辑,本文将介绍几种常用的技术方案,帮助开发者实现

    2024年02月16日
    浏览(31)
  • SpringBoot+RabbitMQ实现超时未支付订单自动取消,localhost:15672没有登录页面。

    简介 安装RabbitMQ需要安装Erlang/OTP,并保持版本匹配。 RabbitMQ官网:RabbitMQ: One broker to queue them all | RabbitMQ RabbitMQ与Erlang/OTP版本对照表:Erlang Version Requirements | RabbitMQ Erlang官网下载:Downloads - Erlang/OTP 1.Windows上安装RabbitMQ前需要安装Erlang。(下载安装不做叙述,除了需要自定义安

    2024年04月15日
    浏览(46)
  • 使用shedlock实现分布式定时任务锁【防止task定时任务重复执行】

    第一步:引入shedlock相关依赖 ShedLock还可以使用Mongo,Redis,Hazelcast,ZooKeeper等外部存储进行协调,例如使用redis则引入下面的包 第二步:创建数据库表结构,数据库表的脚本如下: 第三步:添加shedlock配置类 (定时任务防重复执行的配置类) 第四步:在启动类上添加启动注

    2024年02月10日
    浏览(34)
  • 安装VS2019时出现“无法下载安装文件。请检查Internet连接,然后重试”问题

    近期需要安装VS软件,电脑不能连接外部网络,电脑为Win10操作系统。 本来只想装个VS2005,安装过程中提示兼容性报错,忽略这个提示继续安装,最后不能成功运行项目,提示缺少.NET Framework 1.0版本。 后来在自己可以连网的笔记本上试了一下,发现一开始安装时会提示缺少

    2024年02月15日
    浏览(106)
  • Spring Task 实现定时任务 以及 WebSocket 实现 订单提醒 (学习笔记)

    1.maven坐标 spring-context 2.启动类添加注解 @EnableScheduling 开启任务调度 3.自定义定时任务类 去设置网站设置要 进行得定时任务 cron表达式在线生成器:https://cron.qqe2.com/ 1.导入maven坐标 2.导入websocket组件 3.设置配置类 4.导入代码 前端测试代码

    2024年02月20日
    浏览(28)
  • 封装axios请求重试和路由切换时请求取消

    请求重试函数:这里注意两个变量__retryCount 和retry分别代表当前次数和重试次数。如果请求中没有配置retry则正常进行不会进行重试。 请求取消我这里的场景是路由切换时,将上次路由全部取消也可以配置部分取消。注意变量noCancel,他来控制那些不需要被取消。 回顾axios请

    2024年02月21日
    浏览(33)
  • HTTP调用:你考虑到超时、重试、并发了吗?

    今天,我们一起聊聊进行 HTTP 调用需要注意的超时、重试、并发等问题。 与执行本地方法不同,进行 HTTP 调用本质上是通过 HTTP 协议进行一次网络请求。网络请求必然有超时的可能性,因此我们必须考虑到这三点: 首先,框架设置的默认超时是否合理; 其次,考虑到网络的

    2024年02月11日
    浏览(27)
  • uniapp 出现连接服务器超时,点击屏幕重试

    可以从以下几个方面排查问题:    当 Uniapp 应用出现服务器超时的情况时,可以采取以下步骤进行排查: 1. 检查网络连接是否正常:首先需要检查网络连接是否正常,包括本地网络和服务器网络,确保网络连接稳定。 2. 检查服务器是否正常:需要检查服务器是否正常运行,

    2024年02月16日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包