【问题标题】:Generic Retry Logic for code where Constructor Can Throw构造函数可以抛出的代码的通用重试逻辑
【发布时间】:2016-12-21 20:58:34
【问题描述】:

从这里的问题跟进: Cleanest way to write retry logic?

在答案中,定义并使用了一个用于重试函数的泛型类:

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

你将如何实现一个通用重试,构造函数也可以抛出?

所以我不想重试:

   SomeFunctionThatCanFail() 

我想以通用方式重试以下块:

   SomeClass sc = new SomeClass();
   sc.SomeFunctionThatCanFail();

【问题讨论】:

  • 如果以后不需要访问sc,可以新建Retry.Do(() => new SomeClass().SomeFunctionThatCanFail(), TimeSpan.FromSeconds(1));
  • “构造函数可以抛出的地方”对我来说听起来很可疑。是的,构造函数可能会抛出,但必须是严重错误。不是第二次尝试的东西
  • 问题的假设是ctor可以抛出;大概没有办法防止 ctor 抛出,因为如果有,你会这样做,然后你就不需要重试了。但是问题的附加假设是再次做同样的事情不会抛出。所以,你有一个无法预测的演员。不要在该代码上贴创可贴;删除它并编写一个行为可预测的 ctor。
  • @EricLippert 我实际上打算在我的帖子中链接Vexing exceptions,哈哈......
  • 指数退避是一个很好的重试策略,而不是简单地尝试 x 次。您可以使用 Polly 之类的库来实现它。

标签: c# retry-logic


【解决方案1】:

构造函数还可以抛出哪里?

通常这是一个坏主意。我建议查看工厂模式:

public class SomeClass
{
  private SomeClass()
  {
  }

  public static SomeClass GetInstance()
  {
    // Throw Exception here, not in constructor
  }

  public void SomeFunctionThatCanFail()
  {
  }
}

现在你可以这样做了:

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

【讨论】:

    【解决方案2】:

    我没有意识到我可以将一段代码放入 Lambda 表达式中。这正是我想要的:

    Retry.Do(() => { using (DataBaseProxy db = new DataBaseProxy(dbList.Next())) { .DoSomething(); } }, new TimeSpan(0));
    

    【讨论】:

      猜你喜欢
      • 2021-06-11
      • 1970-01-01
      • 2016-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-09
      • 1970-01-01
      相关资源
      最近更新 更多