一个简单的异常/条件重试类(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 ...
随机推荐
- 用sublime server 启动本地服务器(手机访问电脑页面)
安装sublime server 插件包 1.Ctrl + shift + p install package ...
- [译]贵宾犬咬伤了TLS
原文链接:https://community.qualys.com/blogs/securitylabs/2014/12/08/poodle-bites-tls 原文发表时间:2014.12.8 今天 ...
- BZOJ4033 HAOI2015 树上染色 【树上背包】
BZOJ4033 HAOI2015 树上染色 Description 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并将其他的N-K个点染成白 ...
- BZOJ1690 Usaco2007 Dec 奶牛的旅行 【01分数规划】
BZOJ1690 Usaco2007 Dec 奶牛的旅行 题目描述 作为对奶牛们辛勤工作的回报,Farmer John决定带她们去附近的大城市玩一天.旅行的前夜,奶牛们在兴奋地讨论如何最好地享受这难得 ...
- Page View Controllers
Page View Controllers You use a page view controller to present content in a page-by-page manner. A ...
- win32 去掉窗口边框
参考:http://www.blitzbasic.com/Community/posts.php?topic=67222 Strict Graphics 320, 200 SetClsColor 0, ...
- [深度学习]Python/Theano实现逻辑回归网络的代码分析
2014-07-21 10:28:34 首先PO上主要Python代码(2.7), 这个代码在Deep Learning上可以找到. # allocate symbolic variables for ...
- 关于CSS单位:rem vh vw vmin vmax
rem(root em) 如果你给body设置了font-size字体大小,那么body的任何子元素的1em就是等于body设置的font-size demo: body { font-size: ...
- Makefile编写 五 隐含规则
隐含规则———— 在我们使用Makefile时,有一些我们会经常使用,而且使用频率非常高的东西,比如,我们编译C/C++的源程序为中间目标文件(Unix下是[.o]文件,Windows下是[.obj] ...
- GDB调试字符数组时指针和数组区别的体现
测试ftell函数时发现报错,先贴源码 // File Name: ftell.c #include <stdio.h> #include <stdlib.h> int mai ...