【问题标题】:Call a method n number of times [closed]调用方法n次[关闭]
【发布时间】:2017-01-11 23:51:23
【问题描述】:
int noOfAttempts = 3;
void StartServer();
bool IsServerRunning();

我需要根据IsServerRunnig() 的结果重新尝试StartServer() 3 次。像这样的:

StartServer();
if (!IsServerRunning())
{
    StartServer();
    if (!IsServerRunning())
    {
        StartServer();
        if (!IsServerRunning())
        {
            StartServer();
        }
    }
}

我不想像上面那样使用 for 循环或丑陋的代码。有没有更好的方法来做到这一点?如果将来noOfAttempts 发生变化,我不必更改代码?

编辑: 我期待从“代表”概念中得到一些东西(如果可能的话)。

【问题讨论】:

  • 为什么不想使用 for 循环?这似乎是一个很好的结构。
  • @Oded:如果 noOfAttempts 发生变化,那么我将不得不在代码中添加另一个 if 条件。
  • 我不明白为什么会这样,如果你正确使用 for 循环就不会。
  • 应该为此使用循环。追求更复杂和与众不同的东西是 0 意义。
  • 如果我想尝试新的东西有什么问题?它可能在其他复杂的情况下对我有所帮助。众所周知的事实是循环被设计用于这种事情..但只是尝试开箱即用..

标签: c# .net


【解决方案1】:

UPD

似乎您实际上想要(编辑)一些巧妙的方式来描述重试逻辑。在这种情况下,请查看瞬态故障处理库,例如 Polly


好的。

3.TimesUntil(IsServerRunning, StartServer); 

在这里展示魔法:

public static class Extensions 
{
    public static void TimesWhile(this int count, Func<bool> predicate, Action action)
    {
        for (int i = 0; i < count && predicate(); i++) 
           action();
    }
    public static void TimesUntil(this int count, Func<bool> predicate, Action action)
    {
        for (int i = 0; i < count && !predicate(); i++) 
            action();
    }
}

致尊敬的反对者: 这只是为了好玩,我永远不会为实际项目编写此代码。

【讨论】:

  • i 应该每次递增,否则你将一直持续到成功(或在失败的情况下永远)
  • 它会起作用,并且它使用代表......但这是一派胡言。它不必要地复杂。不明白,这么简单的任务为什么不用循环呢。
  • @mlorbetske,谢谢,我忘了 :)
  • @Jakub Szułakiewicz,因为 Sandeep 问道。当然只是为了好玩)
  • 但是哦,天哪... OP 可能不想使用它,因为它仍然包含一个“for”循环
【解决方案2】:

你可以使用while循环

int counter = 0;
while(counter < 3 && !IsServerRunning()) {
    StartServer();
    counter++;
}

【讨论】:

    【解决方案3】:

    这里没有循环...

    private void Start(int numberOfAttempts)
    {
        if (numberOfAttempts == 0)
            return;
    
        StartServer();
    
        if (!IsServerRunning())
            Start(numberOfAttempts-1);
    }
    

    【讨论】:

    • 设为Start(--numberOfAttempts)Start(numberOfAttempts-1) 否则你将面临无限递归。
    【解决方案4】:

    正如大家已经注意到的那样,while 或 for 循环确实是解决这个问题最简单的部分。

    如果您真的想为这些东西设置一些非常高级的东西,请查看trampoline function question 或查看article from Bart。使用这种方法,您将能够避免循环(因此我认为在这种情况下不值得)。

    【讨论】:

      【解决方案5】:

      当然:

      while (numRetries > 0 && !IsServerRunning) {
          StartServer();
          numRetries--;
      }
      

      如果你喜欢冒险,你也可以使用goto ;-)

      【讨论】:

        【解决方案6】:

        如果你真的想要的话,你可以使用一个委托..(也许是一个可重用的东西库?)

        public void CallFunctionNTimes(Action func, int nTimes, params bool[] conditions) {
            int callCounter = 0;
        
            while (callCounter < nTimes && conditions.All(x => x == true)) {
                func();
                callCounter++;
            }
        }
        

        用法:

        CallFunctionNTimes(StartServer, 3, !IsServerRunning /* Other stuff too if you want */);
        

        .. 与其他答案没有太大不同,除了我猜它可以重复使用:)

        【讨论】:

          【解决方案7】:

          我可能会将其作为StartServer 方法本身的内置功能。像这样的东西(只是一个概念证明):

          public class ServerNotRunningException : Exception { /*No content here*/ }
          
          public void StartServer(int attempts = 3)
          {
              try
              {
                  //attempt to start server
                  if(!IsServerRunning()) // or check something available in your method
                      throw new ServerNotRunningException();
              }
              catch(ServerNotRunningException ex)
              {
                  // you should log ex.ToString() here!
                  if(attempts>0) StartServer(attempts-1); //try again!
                  else throw new ServerNotRunningException(); //mission failed, bubble up!
              }
          }
          

          用法:

          StartServer();
          //or, to make it try i.e. 5 times
          StartServer(5);
          

          【讨论】:

            【解决方案8】:

            do..while(false) 循环怎么样? (开玩笑,但说真的,我以前在代码中见过)

            int numTries;
            
                    do
                    {
                        if(numTries == 0)
                            break;
            
                        StartServer();
                        numTries--;
            
                        if (!IsServerRunning)
                            continue;
                    } while (false);
            

            【讨论】:

              【解决方案9】:
              int numberOfAttempts = 3;
              
              do
              {
                  StartServer();
                  numberOfAttempts--;
              } 
              while(!IsServerRunning() && numberOfAttempts > 0)
              

              UPDATE:因此这些操作是密切相关的,你可以创建方法

              bool TryStartServer()
              {
                   StartServer();
                   return IsServerRunning();
              }
              

              第二个,会尝试多次启动服务器(并返回运行结果)

              bool TryStartServer(int numberOfAttemtps)
              {
                  for(int attempt = 0; attempt < numberOfAttempts; attempt++)
                      if (TryStartServer)
                          return true;
              
                  return false; 
              }
              

              【讨论】:

                【解决方案10】:

                最好将重试逻辑与主代码完全分开:

                void Attempt(Action action, Func<bool> ensure, int noOfAttempts)
                {
                   while (noOfAttempts-- > 0 && !ensure())
                   {
                       action();
                   }
                }
                

                然后:

                Attempt(action:StartServer, ensure:IsServerRunning, noOfAttempts:3)
                

                【讨论】:

                  【解决方案11】:

                  只是为了好玩

                  var calls = Enumerable.Repeat<List<string>>(new List<string>() { "IsServerRunning", "StartServer" }, noOfAttempts).ToList();
                  calls.ForEach(new Action<List<string>>(
                      delegate(List<string> item)
                      {
                          // Use reflection here to create calls to the elements of item
                      }
                  ));
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-11-23
                    • 2020-07-14
                    • 2018-02-06
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-04-03
                    相关资源
                    最近更新 更多