区块链技术博客
www.b2bchain.cn

如何重试直到满足某些条件 – c#程序员分享

本文介绍了如何重试直到满足某些条件 – c#程序员分享,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

我需要重试某种方法,直到它返回非空的Guid。

有一个很棒的answer会根据是否存在异常重试;但是,我想将此类通用化,以便能够处理任何指定的条件。

当前用法将执行特定次数的操作,直到没有例外:

Retry.Do(() => SomeFunctionThatCanFail(), TimeSpan.FromSeconds(1)); 

要么:

Retry.Do(SomeFunctionThatCanFail, TimeSpan.FromSeconds(1)); 

要么:

int result = Retry.Do(SomeFunctionWhichReturnsInt, TimeSpan.FromSeconds(1), 4); 

如何修改此类,使其根据传入的函数的返回值重试?

例如,如果我想重试直到函数返回3:

Retry.Do(() => SomeFunctionThatCanFail(), TimeSpan.FromSeconds(1)).Until(3); 

这意味着每隔1秒执行SomeFunctionThatCanFail()直到SomeFunctionThatCanFail()= 3?

在满足条件之前,我如何概括Retry.Do的用法?

public static class Retry {    public static void Do(        Action action,        TimeSpan retryInterval,        int retryCount = 3)    {        Do<object>(() =>         {            action();            return null;        }, retryInterval, retryCount);    }     public static T Do<T>(        Func<T> action,         TimeSpan retryInterval,        int retryCount = 3)    {        var exceptions = new List<Exception>();         for (int retry = 0; retry < retryCount; retry++) //I would like to change this logic so that it will retry not based on whether there is an exception but based on the return value of Action        {           try           {                if (retry > 0)                   Thread.Sleep(retryInterval);               return action();           }           catch (Exception ex)           {                exceptions.Add(ex);           }        }         throw new AggregateException(exceptions);    } } 

参考方案

如何创建以下界面:

public interface IRetryCondition<TResult> {      TResult Until(Func<TResult, bool> condition); }  public class RetryCondition<TResult> : IRetryCondition<TResult> {      private TResult _value;      private Func<IRetryCondition<TResult>> _retry;       public RetryCondition(TResult value, Func<IRetryCondition<TResult>> retry)      {          _value = value;          _retry = retry;      }       public TResult Until(Func<TResult, bool> condition)      {          return condition(_value) ? _value : _retry().Until(condition);      } } 

然后,您将更新您的Retry静态类:

public static class Retry {     // This method stays the same     // Returning an IRetryCondition does not make sense in a "void" action     public static void Do(        Action action,        TimeSpan retryInterval,        int retryCount = 3)     {         Do<object>(() =>          {             action();             return null;         }, retryInterval, retryCount);     }      // Return an IRetryCondition<T> instance     public static IRetryCondition<T> Do<T>(        Func<T> action,         TimeSpan retryInterval,        int retryCount = 3)     {         var exceptions = new List<Exception>();          for (int retry = 0; retry < retryCount; retry++)         {             try             {                 if (retry > 0)                   Thread.Sleep(retryInterval);                 // We return a retry condition loaded with the return value of action() and telling it to execute this same method again if condition is not met.                return new RetryCondition<T>(action(), () => Do(action, retryInterval, retryCount));             }             catch (Exception ex)             {                  exceptions.Add(ex);             }         }          throw new AggregateException(exceptions);     } } 

您将能够实现以下目标:

int result = Retry.Do(() => SomeFunctionThatCanFail(), TimeSpan.FromSeconds(1)).Until(r => r == 3); 

更实用的方法
我试图提出一个更加“面向功能”的解决方案(有点类似于LINQ):
首先,我们将有两个接口来执行操作:

public interface IRetryResult {     void Execute(); }  public interface IRetryResult<out TResult> {     TResult Execute(); } 

然后,我们需要两个接口来配置重试操作:

public interface IRetryConfiguration : IRetryResult {     IRetryConfiguration Times(int times);     IRetryConfiguration Interval(TimeSpan interval); }  public interface IRetryConfiguration<out TResult> : IRetryResult<TResult> {     IRetryConfiguration<TResult> Times(int times);     IRetryConfiguration<TResult> Interval(TimeSpan interval);     IRetryConfiguration<TResult> Until(Function<TResult, bool> condition); } 

最后,两个接口都需要两种实现:

public class ActionRetryConfiguration : IRetryConfiguration {     private readonly Action _action;     private readonly int? _times;     private readonly TimeSpan? _interval;      public ActionRetryConfiguration(Action action, int? times, TimeSpan? interval)     {         _action = action;         _times = times;         _interval = interval;     }      public void Execute()     {         Execute(_action, _times, _interval);     }      private void Execute(Action action, int? times, TimeSpan? interval)     {         action();         if (times.HasValue && times.Value <= 1) return;         if (times.HasValue && interval.HasValue) Thread.Sleep(interval.Value);         Execute(action, times - 1, interval);     }      public IRetryConfiguration Times(int times)     {         return new ActionRetryConfiguration(_action, times, _interval);     }      public IRetryConfiguration Interval(TimeSpan interval)     {         return new ActionRetryConfiguration(_action, _times, interval);     } }   public class FunctionRetryConfiguration<TResult> : IRetryConfiguration<TResult> {     private readonly Func<TResult> _function;     private readonly int? _times;     private readonly TimeSpan? _interval;     private readonly Func<TResult, bool> _condition;      public FunctionRetryConfiguration(Func<TResult> function, int? times, TimeSpan? interval, Func<TResult, bool> condition)     {         _function = function;         _times = times;         _interval = interval;         _condition = condition;     }      public TResult Execute()     {         return Execute(_function, _times, _interval, _condition);     }      private TResult Execute(Func<TResult> function, int? times, TimeSpan? interval, Func<TResult, bool> condition)     {         TResult result = function();         if (condition != null && condition(result)) return result;         if (times.HasValue && times.Value <= 1) return result;         if ((times.HasValue || condition != null) && interval.HasValue) Thread.Sleep(interval.Value);         return Execute(function, times - 1, interval, condition);     }      public IRetryConfiguration<TResult> Times(int times)     {         return new FunctionRetryConfiguration<TResult>(_function, times, _interval, _condition);     }      public IRetryConfiguration<TResult> Interval(TimeSpan interval)     {         return new FunctionRetryConfiguration<TResult>(_function, _times, interval, _condition);     }      public IRetryConfiguration<TResult> Until(Func<TResult, bool> condition)     {         return new FunctionRetryConfiguration<TResult>(_function, _times, _interval, condition);     } } 

最后,Retry静态类,入口点:

public static class Retry {     public static IRetryConfiguration Do(Action action)     {         return new ActionRetryConfiguration(action, 1, null);     }      public static IRetryConfiguration<TResult> Do<TResult>(Func<TResult> action)     {         return new FunctionRetryConfiguration<TResult>(action, 1, null, null);     } } 

我认为这种方法比较容易出错,而且更清洁。
此外,它还允许您执行以下操作:

int result = Retry.Do(SomeIntMethod).Interval(TimeSpan.FromSeconds(1)).Until(n => n > 20).Execute();  Retry.Do(SomeVoidMethod).Times(4).Execute(); 

This question already has answers here: Closed 7 years ago. Possible Duplicate: What does >> and >>> mean in Java?我在一些Java代码中遇到了一些陌生的符号,尽管代码可以正确编译和运行,但对于括号在此代码中的作用却感…

我在util.TreeSet类中发现,其中一个构造函数正在使用具有空泛型类型的新TreeMap调用另一个构造函数。 public TreeSet(Comparator<? super E> comparator) { this(new TreeMap<>(comparator)); } new TreeMap<>是什么意思…

我正在尝试为我的项目之一获得声纳报告。我已经运行mvn clean installRunning blah.blah.BlahTest1 Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.016 sec Running blah.blah.BlahTest2 Tests run…

我有以下表格:@Entity @Table(name = "events") Event –id –name @Entity @Table(name = "state") State –id –name @Entity @Table(name = "action") Action –id …

尝试从nyc Wiki页面中的高中列表中获取所有高中名称。我已经写了足够多的脚本,可以让我获取包含在高中,学业和入学条件列表的表的<tr>标记中的所有信息-但是我如何才能缩小到我认为的范围内在td[0]内休息(会弹出KeyError)-只是学校的名称?到目前为止我写的代码:from bs4 import BeautifulSoup from ur…

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » 如何重试直到满足某些条件 – c#程序员分享
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们