一个简单的异常/条件重试类(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 ...
随机推荐
- UNIX 基础知识
登陆 1.登录名 系统在其 口令文件(通常是/etc/passwd文件) 中查看用户名,口令文件中包含了有关用户的信息. 2.shell ...
- MySQL存储引擎(engine:处理表的处理器)
1.基本的操作命令: 1.查看所有存储引擎 show engines: 2.查看已有表的存储引擎: show create table 表名: 3.创建表指定的存储引擎 create table 表名 ...
- Android:数据持久化(1/2)文件、SharedPreferences
Summary 持久化的3种方法: 普通文件:I/O流操作文件: SharedPreferences:XML文件,通过key-value pair的形式存储数据: SQLite:Android自带数据 ...
- ios 视图切换翻页效果
本文写的是视图切换,涉及到的内容有 1.实现代码添加Navigation Bar Toolbal: 2.实现在Navigation Bar和Toolbar上用代码添加Bar Button Item: ...
- Python学习-字典练习:简单通讯录
功能要求: 查询联系人,输入姓名,可以查询当前通讯录里面的联系人信息,若联系人存在,则输出联系人信息,若不存在,则告知 插入联系人,可以向通讯录中新建联系人,若联系人已经存在,则询问是否修改联系人信息 ...
- ballerina 学习十三 函数&&documentation
ballerina 函数和其他语言一样的,可以实现重用 简单例子 代码 import ballerina/io; documentation { `User` is a user defined ob ...
- IDEA使用介绍
https://blog.csdn.net/qq_27093465/article/details/77449117
- [LeetCode系列]括号生成问题
给定n, 返回所有匹配的n对括号的可能形式. 如 给定 n = 3, 一个解集是: "((()))", "(()())", "(())()" ...
- hadoop之 HDFS-Hadoop存档
每个文件按块方式存储, 每个块的元数据存储在namenode的内存中 Hadoop存档文件或HAR文件是一个更高效的文件存档工具,它将文件存入HDFS块,在减少内存使用的同时,允许对文件进行透明地访问 ...
- yum安装postgresql
https://wiki.postgresql.org/wiki/YUM_Installation