单个类,简单好用

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#)的更多相关文章

  1. 实现一个简单的http请求工具类

    OC自带的http请求用起来不直观,asihttprequest库又太大了,依赖也多,下面实现一个简单的http请求工具类 四个文件源码大致如下,还有优化空间 MYHttpRequest.h(类定义, ...

  2. Qt5.9一个简单的多线程实例(类QThread)(第一种方法)

    Qt开启多线程,主要用到类QThread.有两种方法,第一种用一个类继承QThread,然后重新改写虚函数run().当要开启新线程时,只需要实例该类,然后调用函数start(),就可以开启一条多线程 ...

  3. 一个简单小巧的CSV读取类

    最近在基于亚马逊MWS API做一些服务,需要读取亚马逊返回的报表,是一个按照\t分割的文本,所以就封装了一个简单小巧的CsvReader类 使用方法 使用方法非常简单,只需要传递一个stream子类 ...

  4. Java下一个简单的数据库分库帮助类

    简介    前面两篇文章主要讲了数据库读写分离和分表分库的一些问题,这篇文章主要讲一下我个人实现的一个分表分库项目.     在此之前,我有写过一个.Net的分库,最近在做Java的项目,就顺便做出一 ...

  5. 一个简单IP防刷工具类, x秒内最多允许y次单ip操作

    IP防刷,也就是在短时间内有大量相同ip的请求,可能是恶意的,也可能是超出业务范围的.总之,我们需要杜绝短时间内大量请求的问题,怎么处理? 其实这个问题,真的是太常见和太简单了,但是真正来做的时候,可 ...

  6. 一个简单清晰的Redis操作类

    <?php /** * redis处理的二次封装 * */ class Redis{ private $_redis; private $_config; public function __c ...

  7. 一个简单清晰的Redis操作类-php

    <?php /** * redis处理的二次封装 * */ class Redis{ private $_redis; private $_config; public function __c ...

  8. 分享给大家一个简单的数据导出excel类

    <?php /** * 生成excel文件操作 * * @author wesley wu * @date 2013.12.9 */ class Excel { private $limit = ...

  9. 一个简单的Java文件工具类

    package com.xyworkroom.ntko.util; import java.io.File; import java.io.FileInputStream; import java.i ...

随机推荐

  1. PHP convet class to json data

    /********************************************************************* * PHP convet class to json da ...

  2. c语言输出4*5的数列?

    1 2 3 4 5 2 4 6 8 10 3 6 9 12 15 4 8 12 16 20   输出上面的数列,用c实现的代码:<pre lang="c" line=&quo ...

  3. 每天一个linux命令:【转载】tail命令

    tail 命令从指定点开始将文件写到标准输出.使用tail命令的-f选项可以方便的查阅正在改变的日志文件,tail -f filename会把filename里最尾部的内容显示在屏幕上,并且不但刷新, ...

  4. BZOJ4518 Sdoi2016 征途 【斜率优化DP】 *

    BZOJ4518 Sdoi2016 征途 Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地.除第m ...

  5. 使用 Emit 生成 IL 代码

    .NET Core/.NET Framework 的 System.Reflection.Emit 命名空间为我们提供了动态生成 IL 代码的能力.利用这项能力,我们能够在运行时生成一段代码/一个方法 ...

  6. 深入了解 WPF Dispatcher 的工作原理(PushFrame 部分)

    在上一篇文章 深入了解 WPF Dispatcher 的工作原理(Invoke/InvokeAsync 部分) 中我们发现 Dispatcher.Invoke 方法内部是靠 Dispatcher.Pu ...

  7. lua不支持的泛型方法

    1.没有泛型约束 2.缺少带约束的泛型参数 3.泛型约束必须为class /// <summary> /// 不支持生成lua的泛型方法(没有泛型约束) /// </summary& ...

  8. MySQL中地理位置数据扩展geometry的使用心得

    最近学习了些MySQL geometry数据存储和计算,在这里记录下. 1. 环境 geometry推荐在5.6版本以上使用,尽管大部分功能在5.5已经可用,除了距离计算函数st_distance等新 ...

  9. 用vs2010编译vs2013建的工程

    第一步,用文本打开,修改.sln文件 原始: Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2 ...

  10. kotlin与fastjson的异常

    出现这个原因是因为kotlin的非空特性. 如果一个类中声明了一个字段(kotlin的特性,该字段默认是非空的), 使用fastjson进行转化的时候,如果json数据中没有该字段的数据,则会出现转换 ...