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

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

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

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

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

4

11 回答 11

9

更新

似乎您实际上想要(编辑)一些巧妙的方式来描述重试逻辑。在这种情况下,请查看诸如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();
    }
}

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

于 2012-10-16T08:46:15.150 回答
7

你可以使用一个while循环

int counter = 0;
while(counter < 3 && !IsServerRunning()) {
    StartServer();
    counter++;
}
于 2012-10-16T08:32:07.783 回答
6

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

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

    StartServer();

    if (!IsServerRunning())
        Start(numberOfAttempts-1);
}
于 2012-10-16T08:34:47.800 回答
1

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

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

于 2012-10-16T08:46:02.743 回答
0

当然:

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

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

于 2012-10-16T08:32:53.990 回答
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; 
}
于 2012-10-16T08:34:02.680 回答
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 */);

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

于 2012-10-16T08:39:13.827 回答
0

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

int numTries;

        do
        {
            if(numTries == 0)
                break;

            StartServer();
            numTries--;

            if (!IsServerRunning)
                continue;
        } while (false);
于 2012-10-16T08:42:53.367 回答
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);
于 2012-10-16T08:43:17.437 回答
-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
    }
));
于 2012-10-16T12:55:52.933 回答
-1

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

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

接着:

Attempt(action:StartServer, ensure:IsServerRunning, noOfAttempts:3)
于 2012-10-16T08:40:05.457 回答