-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

UPD

再試行ロジックを説明するための適切な方法が実際に必要なようです。この場合、Pollyなどの一時的な障害処理ライブラリを見てください。


Ok。

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

そして2つ目は、サーバーを数回起動しようとします(そして操作の結果を返します)

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

再試行ロジックをメインコードから完全に分離することをお勧めします。

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 に答える
-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 に答える