zoukankan      html  css  js  c++  java
  • 一个简单的异常/条件重试类(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好。

  • 相关阅读:
    记录centos中pptpd server 的配置
    记录IIS7.5的rewrite配置
    duration异常导致的移动端音频无法播放问题
    移动端web开发的几个tips记录
    关于ie8中微软雅黑字体显示的问题
    移动端audio使用的一个注意事项
    关于window.opener的一个小记录
    【翻译】行高的相关计算
    spring 事务管理(编程式)
    CSDN上看到的一篇有关Spring JDBC事务管理的文章(内容比较全)
  • 原文地址:https://www.cnblogs.com/yesicoo/p/9565065.html
Copyright © 2011-2022 走看看