在上位机和MES通信,尤其是上位机向MES发送数据的的时候,经常需要设置一个超时处理的时间和重复执行的次数。例如MES的超时响应事件是5秒,超过5秒的话,上位机重新访问MES一次,连续三次都超时的话,把要上传的数据缓存到本地。

关于上位机和MES系统的通讯方式,有的工厂是WebService(数据格式有JSON和XML之分),有的工厂是Socket,有的工厂是自己封装的库,所以写了段儿程序执行任务的代码,通讯方式如何都可以写到TASK中

        /// <summary>/// 执行任务超时的话,取消当前执行的任务,重新执行任务。/// 在最大重新执行次数内执行完,则执行onSuccess委托/// 执行次数达到最大执行次数,任务还是超时的话,则执行onFailure委托/// </summary>/// <param name="operation">要执行的任务</param>/// <param name="maxRetryCount">最大重复执行的次数</param>/// <param name="timeout">单次执行任务超时的时间</param>/// <param name="onSuccess">在最大重新执行次数内执行完,执行的委托</param>/// <param name="onFailure">执行次数达到最大执行次数,任务还是超时的话,执行的委托        </param>/// <returns></returns>public static async Task ExecuteWithRetriesAsync(Func<Task> operation,int maxRetryCount,TimeSpan timeout,Func<Task> onSuccess,Func<Task> onFailure){while (true){if (maxRetryCount == 0){// 超过最大重试次数,执行失败委托并退出函数await onFailure(); //失败该走的事情,比如把数据缓存到本地return;}var task = operation();if (await Task.WhenAny(task, Task.Delay(timeout)) == task){try{// 如果成功,执行成功委托并退出函数await onSuccess();return;}catch (OperationCanceledException ex){Console.WriteLine($"任务超时取消, message: {ex.Message}" + " " + DateTime.Now);}}else{// 超时,取消任务await CancelTaskAsync(task);}Console.WriteLine($"任务超时,重试任务, retry count: {maxRetryCount}");maxRetryCount--;}}/// <summary>/// 取消任务/// 在 CancelTaskAsync 方法中,不应该释放 CancellationTokenSource 对象,它的责任只是调用任务并稍后取消它(用于超时)。/// 在正常情况下,CancellationTokenSource对象将由垃圾回收器在不再使用它时自动释放。因此,在 CancelTaskAsync 中不需要对 cts 对象进行显式释放。/// </summary>/// <param name="task"></param>/// <returns></returns>public static async Task CancelTaskAsync(Task task){var cts = new CancellationTokenSource();try{cts.Cancel();await task;}catch (OperationCanceledException ex){Console.WriteLine($"任务取消CancelTaskAsync, message: {ex.Message}");}}/// <summary>/// 模拟一个需要很长时间才能执行完毕的任务/// </summary>/// <param name="timeOutSec"></param>/// <returns></returns>public static async Task LongRunningOperationAsync(int timeOutSec){using (var tokenSource = new CancellationTokenSource()){Console.WriteLine("");// 确保在超时后取消任务tokenSource.CancelAfter(TimeSpan.FromSeconds(timeOutSec));// 在任务执行期间定期检查 CancellationToken,// 假设当前任务要执行8秒await Task.Delay(TimeSpan.FromSeconds(8), tokenSource.Token);Console.WriteLine("****Operation succeeded.");}}

注意上面这段代码使用了 Task.WhenAny 方法,该方法接受一个 Task 对象数组,并返回一个 Task<Task> 对象,该对象的结果是完成最先完成的 Task 对象。使用 await 运算符等待 Task.WhenAny 方法返回的 Task,这将导致代码在这里等待,直到指定的任务 task 或超时任务 Task.Delay 完成为止。 如果最先完成的任务是指定的任务 task,则 Task.WhenAny 的返回结果即为 task,这意味着 await Task.WhenAny(task, Task.Delay(timeout)) 将返回 task 对象的结果,此时,if 语句的条件判断结果为 True,进入 if 块内部的代码。否则,如果超时任务先完成,Task.WhenAny 的返回结果将是超时任务 Task.Delay,在这种情况下,if 语句将不会执行,代码将继续执行 Task.Delay 后面的语句。 因此,这个 if 语句是用来确定任务是否在规定的超时时间内完成的。如果完成,在 if 块内部执行相应的代码;如果没有,在超时后执行某种其他的操作。

模拟条件执行任务,模拟超时的时间为5秒,最多执行任务3次。

public static async Task DoSomethingAgainAndAgain(){// 累计重试和最大重试次数初始化int maxRetryCount = 3;//最多执行任务的次数int timeOutSec = 5;//每次执行任务的超时时间// 成功和失败的委托初始化Func<Task> onSuccess = () => Task.FromResult<object>("do nothing");Func<Task> onFailure = () => Task.FromResult<object>("do nothing");// 执行异步任务并在超时后重试最大重试次数await ExecuteWithRetriesAsync(async () => await LongRunningOperationAsync(timeOutSec),maxRetryCount,TimeSpan.FromSeconds(timeOutSec),onSuccess, onFailure);}

也可以用下面这种方法来模拟任务

static async Task LongRunningOperationAsync2(int timeOutSec){using (var tokenSource = new CancellationTokenSource()){var startTime = DateTime.Now;// 在任务执行期间定期检查 CancellationToken,// 如果它已取消,可以安全地退出。while (true){if ((DateTime.Now - startTime) >= TimeSpan.FromSeconds(timeOutSec)){tokenSource.Cancel();}if (tokenSource.IsCancellationRequested){return;}await Task.Delay(TimeSpan.FromSeconds(1));}}}

编写上述代码用了如下知识点,这些都很重要,希望大家好好学习,天天想上

  1. 异步编程 - ExecuteWithRetriesAsync 方法的定义和实现都是基于异步编程模型的。

  2. 委托和Lambda表达式 - 函数 ExecuteWithRetriesAsync 接受两个参数类型为 Func<Task> 的委托参数,在函数体内被直接调用,使用了 Lambda 表达式来定义这些委托。

  3. 异常处理 - 为了捕获可能在异步执行过程中产生的异常,代码块使用了 try/catch 语句。

  4. Task 和 Task.Delay - Task 类型用于表示异步操作的进程,而 Task.Delay 方法用于异步延迟一段时间后执行一个操作。

  5. Task.WhenAny - Task.WhenAny 方法用于等待任何一个任务完成,如果第一个任务完成,则返回该任务,如果没有完成,则返回一个默认的任务。在这个方法中,使用 Task.WhenAny 方法来判断当前任务是否已经超时。

  6. async/await 关键字 - 使用了 async/await 关键字以帮助简化对异步方法的调用

C#执行任务Task,如果任务超时的话就取消当前任务,重新执行,规定次数内执行成功则执行成功的委托,超过规定的次数则失败的委托相关推荐

  1. build 之前执行task_Android Gradle新增buildtypes以及编译前执行自定义task

    众所周知,打包的需求千奇百怪,我们在打包时会遇到文件操作.版本定义.通过参数控制版本之类的需求.今天我们就来聊聊如何来实现这些需求-- 1.添加buildTypes 一般我们通过gradle构建的命令 ...

  2. python怎么连接远程服务器没有按时响应_python通过paramiko执行ssh命令时设置超时时间 - Python - 服务器之家...

    python通过paramiko执行ssh命令时设置超时时间 发布时间:2014-06-17

  3. try代码块中出现异常后try内程序会继续执行还是直接抛出异常?

    @Testpublic void excp() {try {int i = 1/0;System.out.println(1);}catch (Exception e) {e.printStackTr ...

  4. 【Qt】Qt程序编译成功,执行时报错:程序异常结束,crashed

    [Qt]Qt程序编译成功,执行时报错:程序异常结束,crashed 错误打印信息 Starting E:*exe- 程序异常结束. E:*.exe crashed. 原因 使用到外部库,编译时,指定了 ...

  5. 线程其实就是一个个指令组成的,当这个线程内的指令全部执行完了,那么这个线程也就执行结束了

    线程其实就是一个个指令组成的,当这个线程内的指令全部执行完了,那么这个线程也就执行结束了

  6. 新版opencv兼容旧版_【标准换版】关于家用和类似用途电器用外置电源适配器、充电器和内置开关电源产品认证执行新版标准的通知...

    各相关认证企业: GB4343.1-2018<家用电器.电动工具和类似器具的电磁兼容要求 第1部分:发射>标准(以下简称"新版标准")已发布,并将于2020年6月1日实 ...

  7. 为什么element ui 中表单验证validate验证成功不执行验证成功的逻辑代码

    element ui 中表单验证validate验证成功不执行成功的逻辑代码 首先今天做项目时遇到的一个问题,下面代码中,如果上面的验证规则通过但是不会执行验证通过的代码,只有验证不通过才会输出els ...

  8. 为什么执行ACTION_DOWN的时候返回了false,后面一系列其它的action就不会再得到执行了?

    在郭霖大神的博客:Android事件分发机制完全解析,带你从源码的角度彻底理解(上)中有这样一句话: 如果你在执行ACTION_DOWN的时候返回了false,后面一系列其它的action就不会再得到 ...

  9. JS Array.map方法内异步方法无法同步执行

    问题: JS Array.map方法内异步方法无法同步执行 场景: 我们在使用map来设置每一项值的时候,涉及到异步操作,就会出现问题. 按照常规,重现出一种情形. 假设我要使用map对每一项值进行操 ...

最新文章

  1. 北美欧洲顶级大咖齐聚,在这里读懂 AIoT 未来!
  2. 九度 1408 寻找表达式 (中缀转后缀)
  3. Linux安装软件命令小结
  4. MyBatis 通用Mapper 入门教程
  5. C语言 · 约数个数
  6. 陈炳藻用计算机研究,计算机闯入“大观园”
  7. matlab产生ofdm信号,Matlab 完成简单的OFDM 信号的产生与解调程序.pdf
  8. 输入输出系统 2--- 中断(未完)
  9. UESTC_秋实大哥与花 2015 UESTC Training for Data StructuresProblem B
  10. Spring mvc 参数类型转换
  11. JavaScript 代码片段
  12. 机器学习的几种主要学习方法
  13. sql92和sql99的区别
  14. 算法数据结构 | 只要30行代码,实现快速匹配字符串的KMP算法
  15. 计算机提示资源管理器停止,windows资源管理器已停止工作,教您提示win资源管理器已停止工作...
  16. android手势识别国内外研究现状,基于Android平台的视觉手势识别研究
  17. imx6ul-正点原子-imx6ul学习笔记(5)
  18. 004-2018-09-06 列表
  19. 在word表格中设置页码,封面不设置页码,目录页设置罗马数字,正文部分设置阿拉伯数字页码
  20. 【Arch】Android系统简介

热门文章

  1. Linux同步网络时间
  2. oracle 用户锁定 解锁,Oracle用户锁定/解锁
  3. [GitHub] JavaScript 趋势榜项目(第34周)
  4. phpstorm 下载远程代码提示 No files or folders found to process
  5. 名帖62 欧阳询 小楷《心经》
  6. 现在微商怎么做营销?
  7. 接口测试平台代码实现66: 多接口用例-6
  8. 这把联网智能门锁体验感A+
  9. sqlserver数据库详解
  10. java冒泡从大到小排序代码_Java 冒泡排序、快速排序实例代码