一个简单的异常/条件重试类(C#)
单个类,简单好用
using System;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks; namespace Qing
{
public static class QRetry
{
/// <summary>
/// 自定义异常重试
/// </summary>
/// <typeparam name="E"></typeparam>
/// <param name="time"></param>
/// <param name="wait"></param>
/// <param name="action"></param>
/// <param name="retryInfo"></param>
public static void HandException<E>(int time, TimeSpan wait, Action action, Action<E, int, TimeSpan> retryInfo = null) where E : Exception
{
var task = Task.Run(() =>
{
for (int i = 0; i < (time + 1); i++)
{
try
{
action();
break;
}
catch (E e)
{
if (i == time)
{
break;
}
retryInfo?.Invoke(e, i + 1, wait);
Thread.Sleep(wait);
}
} }); }
/// <summary>
/// 自定义异常重试(有返回,异常返回默认值)
/// </summary>
/// <typeparam name="TResult">返回结果</typeparam>
/// <param name="time">次数</param>
/// <param name="wait">等待时间</param>
/// <param name="action">动作</param>
/// <param name="retryInfo">重试信息</param>
/// <returns></returns>
public static TResult HandException<E, TResult>(int time, TimeSpan wait, Func<TResult> action, Action<E, int, TimeSpan> retryInfo = null) where E : Exception
{
return Task.Run(() =>
{
TResult result = default(TResult);
for (int i = 0; i < (time + 1); i++)
{
try
{
result = action();
break;
}
catch (E e)
{
if (i == time)
{
break;
}
retryInfo?.Invoke(e, i + 1, wait);
Thread.Sleep(wait);
}
}
return result;
}).Result;
}
/// <summary>
/// 自定义异常重试(有返回,设置异常返回值)
/// </summary>
/// <typeparam name="TResult">返回结果</typeparam>
/// <param name="time">次数</param>
/// <param name="wait">每次等待时间</param>
/// <param name="failedValue">失败返回值</param>
/// <param name="func">执行方法</param>
/// <param name="retryInfo">重试信息(Exception,Time,TimeSpan)</param>
/// <returns></returns>
public static TResult HandException<E, TResult>(int time, TimeSpan wait, TResult failedValue, Func<TResult> func, Action<E, int, TimeSpan> retryInfo = null) where E : Exception
{
return Task.Run(() =>
{
TResult result = failedValue;
for (int i = 0; i < (time + 1); i++)
{
try
{
result = func();
break;
}
catch (E e)
{
if (i == time)
{
break;
}
retryInfo?.Invoke(e, i + 1, wait);
Thread.Sleep(wait);
}
}
return result;
}).Result;
}
/// <summary>
/// 自定义异常重试
/// </summary>
/// <param name="waits">重试间隔</param>
/// <param name="action">运行方法</param>
/// <param name="retryInfo">重试信息</param>
public static void HandException<E>(TimeSpan[] waits, Action action, Action<E, int, TimeSpan> retryInfo = null) where E : Exception
{
var task = Task.Run(() =>
{
for (int i = 0; i < (waits.Length + 1); i++)
{
try
{
action();
break;
}
catch (E e)
{
if (i == waits.Length)
{
break;
}
retryInfo?.Invoke(e, i + 1, waits[i]);
Thread.Sleep(waits[i]);
}
} });
}
/// <summary>
/// 自定义异常重试 (有返回,异常返回默认值)
/// </summary>
/// <typeparam name="TResult"></typeparam>
/// <param name="waits"></param>
/// <param name="func"></param>
/// <param name="retryInfo"></param>
/// <returns></returns>
public static TResult HandException<E, TResult>(TimeSpan[] waits, Func<TResult> func, Action<E, int, TimeSpan> retryInfo = null) where E : Exception
{
return Task.Run(() =>
{
TResult result = default(TResult);
for (int i = 0; i < (waits.Length + 1); i++)
{
try
{
result = func();
break;
}
catch (E e)
{
if (i == waits.Length)
{
break;
}
retryInfo?.Invoke(e, i + 1, waits[i]);
Thread.Sleep(waits[i]);
}
}
return result;
}).Result;
} /// <summary>
/// 自定义异常重试 (有返回,设置异常返回值)
/// </summary>
/// <typeparam name="TResult"></typeparam>
/// <param name="waits"></param>
/// <param name="func"></param>
/// <param name="retryInfo"></param>
/// <returns></returns>
public static TResult HandException<E, TResult>(TimeSpan[] waits, TResult failedValue, Func<TResult> func, Action<E, int, TimeSpan> retryInfo = null) where E : Exception
{
return Task.Run(() =>
{
TResult result = failedValue;
for (int i = 0; i < (waits.Length + 1); i++)
{
try
{
result = func();
break;
}
catch (E e)
{
if (i == waits.Length)
{
break;
}
retryInfo?.Invoke(e, i + 1, waits[i]);
Thread.Sleep(waits[i]);
}
}
return result;
}).Result;
} /// <summary>
/// 结果判断重试(异常也重试)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="expression"></param>
/// <param name="time"></param>
/// <param name="wait"></param>
/// <param name="func"></param>
/// <param name="retryInfo"></param>
/// <returns></returns>
public static T HandResult<T>(Expression<Func<T, bool>> expression, int time, TimeSpan wait, Func<T> func, Action<string, int, TimeSpan> retryInfo = null)
{
var exp = expression.Compile();
return Task.Run(() =>
{
var result = default(T);
for (int i = 0; i < (time + 1); i++)
{
try
{
result = func();
if (i == time)
{
break;
}
else if (exp.Invoke(result))
{
retryInfo?.Invoke("结果命中约束条件", i + 1, wait);
Thread.Sleep(wait);
continue;
}
else
{
break;
}
}
catch (Exception e)
{
if (i == time)
{
break;
}
retryInfo?.Invoke(e.Message, i + 1, wait);
Thread.Sleep(wait);
}
}
return result;
}).Result; } /// <summary>
/// 结果判断重试(异常也重试)
/// </summary>
/// <typeparam name="T">返回类型</typeparam>
/// <param name="expression">判断表达式</param>
/// <param name="waits">每次重试间隔</param>
/// <param name="func">执行方法</param>
/// <param name="retryInfo">重试信息</param>
/// <returns></returns>
public static T HandResult<T>(Expression<Func<T, bool>> expression, TimeSpan[] waits, Func<T> func, Action<string, int, TimeSpan> retryInfo = null)
{
var exp = expression.Compile();
return Task.Run(() =>
{
var result = default(T);
for (int i = 0; i < (waits.Length + 1); i++)
{
try
{
result = func();
if (i == waits.Length)
{ break;
}
else if (exp.Invoke(result))
{
retryInfo?.Invoke("结果命中约束条件", i + 1, waits[i]);
Thread.Sleep(waits[i]);
continue;
}
else
{
break;
}
}
catch (Exception e)
{
if (i == waits.Length)
{
break;
}
retryInfo?.Invoke(e.Message, i + 1, waits[i]);
Thread.Sleep(waits[i]);
}
}
return result;
}).Result;
}
} }
调用示例:
//调用门店开通方法,依据结果判断Result!="OK",那么过 20秒再重试,一共重试20次
var createResult = Qing.QRetry.HandResult<CreateStoreResult>(x => x.result != "OK", 20, TimeSpan.FromSeconds(20), () =>
{
//开店动作
return StoreManager.Instance.CreateStore(storeArg); }, (msg, count, ts) =>
{
Qing.QLog.SendLog_Debug($"{storeName}开通执行异常:{msg};{ts.TotalSeconds}s 后进行第{count}次重试。");
}
);
方法命名上参考了Polly。正经项目还是用Polly好。
一个简单的异常/条件重试类(C#)的更多相关文章
- 实现一个简单的http请求工具类
OC自带的http请求用起来不直观,asihttprequest库又太大了,依赖也多,下面实现一个简单的http请求工具类 四个文件源码大致如下,还有优化空间 MYHttpRequest.h(类定义, ...
- Qt5.9一个简单的多线程实例(类QThread)(第一种方法)
Qt开启多线程,主要用到类QThread.有两种方法,第一种用一个类继承QThread,然后重新改写虚函数run().当要开启新线程时,只需要实例该类,然后调用函数start(),就可以开启一条多线程 ...
- 一个简单小巧的CSV读取类
最近在基于亚马逊MWS API做一些服务,需要读取亚马逊返回的报表,是一个按照\t分割的文本,所以就封装了一个简单小巧的CsvReader类 使用方法 使用方法非常简单,只需要传递一个stream子类 ...
- Java下一个简单的数据库分库帮助类
简介 前面两篇文章主要讲了数据库读写分离和分表分库的一些问题,这篇文章主要讲一下我个人实现的一个分表分库项目. 在此之前,我有写过一个.Net的分库,最近在做Java的项目,就顺便做出一 ...
- 一个简单IP防刷工具类, x秒内最多允许y次单ip操作
IP防刷,也就是在短时间内有大量相同ip的请求,可能是恶意的,也可能是超出业务范围的.总之,我们需要杜绝短时间内大量请求的问题,怎么处理? 其实这个问题,真的是太常见和太简单了,但是真正来做的时候,可 ...
- 一个简单清晰的Redis操作类
<?php /** * redis处理的二次封装 * */ class Redis{ private $_redis; private $_config; public function __c ...
- 一个简单清晰的Redis操作类-php
<?php /** * redis处理的二次封装 * */ class Redis{ private $_redis; private $_config; public function __c ...
- 分享给大家一个简单的数据导出excel类
<?php /** * 生成excel文件操作 * * @author wesley wu * @date 2013.12.9 */ class Excel { private $limit = ...
- 一个简单的Java文件工具类
package com.xyworkroom.ntko.util; import java.io.File; import java.io.FileInputStream; import java.i ...
随机推荐
- Python环境准备(安装python解释器)
上篇文章介绍了Python的相关知识,本章就开始着手操作,创建第一个Python程序,在这之前,首先需要配置Python的运行环境,也就是安装python解释器 ------------- 完美的分割 ...
- 【集成学习】安装lightgbm
1.下载whl lightgbm的whl下载地址 2.输入命令 pip install lightgbm-2.0.3-py2.py3-one-win_am64.whl 3.验证是否成功 import ...
- RUAL1519 Formula 1 【插头DP】
RUAL1519 Formula 1 Background Regardless of the fact, that Vologda could not get rights to hold the ...
- iOS客户端打包自动集成weex方案
我司在2017年已经部分使用weex开发,然而开发weex 的人都知道,在前端开发完成之后需要集成到 安卓和iOS 各个app 之中.每次修改都要重新copy给各个app 负责人去打包,因此这是一种重 ...
- 洛谷 P1098 字符串的展开
题目描述 在初赛普及组的“阅读程序写结果”的问题中,我们曾给出一个字符串展开的例子:如果在输入的字符串中,含有类似于“d-h”或者“4-8”的字串,我们就把它当作一种简写,输出时,用连续递增的字母或数 ...
- oracle11g卸载(win10)
oracle11g卸载(win10) 0.已在win10安装oracle11g 1.开始->设置->控制面板->管理工具->服务 停止所有Oracle服务. 2.运行Unive ...
- RESTful的一个样例
后台代码: @RequestMapping(value = { "queues" }) @ResponseBody public List<ResourcePool> ...
- C语言 数组排序法总结
//快速排序法 void QuickSort(int *a, int left, int right) { int i = left; int j = right; int k = a[left]; ...
- 在Mac和win7上分别安装了docker后,发现原来的vagrant都启动不了了
在Mac和win7上分别安装了docker后,发现原来的vagrant都启动不了了 liugx@liugx vagrant$ vagrant up /opt/vagrant/embedded/gems ...
- NetCore下模拟和使用Modbus工业通信协议
Tips: 1.目前NetCore下与Modbus通信的框架主要选择了 Modbus.Net https://github.com/parallelbgls/Modbus.Net 2.modbus是 ...