多次调用方法

时间:2012-10-16 08:30:32

标签: c# .net

int noOfAttempts = 3;
void StartServer();
bool IsServerRunning();

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

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

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

编辑: 我期待“委托”概念中的某些内容(如果可能的话)。

11 个答案:

答案 0 :(得分:7)

你可以使用while循环

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

答案 1 :(得分:7)

<强> UPD

看起来你真的想要(ed)一些简洁的方法来描述重试逻辑。在这种情况下,请查看瞬态故障处理库,例如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();
    }
}

尊敬的downvoters: 这只是为了好玩,我永远不会为真正的项目编写这段代码。

答案 2 :(得分:6)

这里你没有循环......

private void Start(int numberOfAttempts)
{
    if (numberOfAttempts == 0)
        return;

    StartServer();

    if (!IsServerRunning())
        Start(numberOfAttempts-1);
}

答案 3 :(得分:1)

正如大家已经注意到一段时间或for循环真的是解决这个问题最容易的部分。

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

答案 4 :(得分:0)

不确定

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

如果您有冒险精神,也可以使用goto; - )

答案 5 :(得分:0)

int numberOfAttempts = 3;

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

更新:因此这个操作密切相关,你可以创建方法

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

第二个,将尝试多次启动服务器(并返回操作结果)

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

    return false; 
}

答案 6 :(得分:0)

如果你真的想要你可以使用委托......(也许是为了可重用的东西?)

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 :(得分:0)

do ... while(false)循环怎么样? (开玩笑,但我以前在代码中看到了它)

int numTries;

        do
        {
            if(numTries == 0)
                break;

            StartServer();
            numTries--;

            if (!IsServerRunning)
                continue;
        } while (false);

答案 8 :(得分:0)

我可能会将它作为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);

答案 9 :(得分:-1)

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

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

然后:

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

答案 10 :(得分:-1)

只是为了好玩

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
    }
));