如果遇到错误,如何重新运行try块?

时间:2010-11-16 13:30:17

标签: c#

  

可能重复:
  C# cleanest way to write retry logic?

我有一个功能包含服务器的Web服务调用,由于网络中的一些干扰,该服务有时失败(无法连接远程服务器错误)。代码在try catch块中。我想在try块中重新运行Web服务调用,以便成功完成Web调用。

11 个答案:

答案 0 :(得分:14)

const int MaxRetries = 5;

for(int i = 0; i < MaxRetries; i++)
{
   try
   {
       // do stuff

       break; // jump out of for loop if everything succeeded
   }
   catch(Exception)
   {
       Thread.Sleep(100); // optional delay here
   }
}

答案 1 :(得分:12)

bool success = false;
int retry = 0;

while (!success && retry<3)
{
    try{
        // web service calls
        success = true;
    } catch(Exception) {
        retry ++;
    }
}

答案 2 :(得分:4)

public void Connect()
{
    Connect(1);
}

private void Connect(int num)
{
    if (num > 3)
        throw new Exception("Maximum number of attempts reached");

    try
    {
        // do stuff
    }
    catch
    {
        Connect(num++);
    }
}

答案 3 :(得分:3)

你可以像这样在try catch块周围放一个循环:

bool repeat = true
while( repeat){
  repeat = false;
  try
  {
    ...
  }
  catch( Exception )   
  {
    repeat = true;
  }
}

答案 4 :(得分:3)

我想你在这里有答案。我只想根据我对此问题的丰富经验添加一些建议。

如果您将日志记录添加到catch块,则可以确定Web服务调用失败的频率,以及所有尝试的次数。 (可能会在web.config中进行切换,以便在问题解决后关闭此注销。)

例如,如果Web服务提供商在您的组织内,例如在Intranet上,则该信息可能在与系统管理员讨论时非常有用。

此外,如果您发现呼叫仍然经常失败,您可能会在catch中引入延迟,以便不立即重试。您可能只想在最后的尝试中这样做。有时值得等待用户,他们不想丢失他们刚刚输入的所有数据。

最后,根据具体情况,您可以在UI中添加“重试”按钮,以便用户可以继续尝试。用户可以选择等待五分钟以使网络问题自行清除,然后单击“重试”。

答案 5 :(得分:2)

在while循环中包装try / catch。成功时设置一个标志以退出while(或仅break)。确保你有某种重试限制,因此它不会永远持续下去。

答案 6 :(得分:2)

while (true)
{
  try
  {
     // call webservice
     // handle results
     break;
  }
  catch (TemporaryException e)
  {
    // do any logging you wish
    continue;
  }
  catch (FatalException e)
  {
    // do any logging you wish
    break;
  }
}

如果要限制重试次数,请更改while循环中的终止条件。

答案 7 :(得分:2)

void Method()
{
    do
    {
        try
        {
            DoStuff();
            return;
        }
        catch (Exception e)
        {
            // Do Something about exception.
        }
    }
    while (true);
}

答案 8 :(得分:2)

如果您发现自己希望在代码中频繁地执行此操作,则可以考虑实现一个可重用的类,该类封装了“遇到错误时重新尝试”逻辑。这样,您可以确保整个代码库中的行为标准化,而不是每次都重复。

Dan Gartner's blog上有一个很好的例子:

public class Retrier<TResult> 
{
    public TResult Try(Func<TResult> func, int maxRetries)
    {
        return TryWithDelay(func, maxRetries, 0);
    }   

    public TResult TryWithDelay(Func<TResult> func, int maxRetries, int delayInMilliseconds)
    {
        TResult returnValue = default(TResult);
        int numTries = 0;
        bool succeeded = false;
        while (numTries < maxRetries)
        {
            try
            {
                returnValue = func();
                succeeded = true;
            }
            catch (Exception)
            {
                //todo: figure out what to do here
            }
            finally
            {
                numTries++;
            }
            if (succeeded)
                return returnValue;
            System.Threading.Thread.Sleep(delayInMilliseconds);
        }
        return default(TResult);
    }
}

答案 9 :(得分:1)

嗯,最简单的方法是将代码复制到catch块,对吧? 另一种方法可能如下:

private void YourMethodThatTriesToCallWebService()
{
    //Don't catch errors
}

public void TryToCallWebService(int numTries)
{
    bool failed = true;
    for(int i = 0; i < numTries && failed; i++)
    {
        try{
             YourMethodThatTriesToCallWebService();
             failed = false;
        }catch{
            //do nothing
        }
    }
}

答案 10 :(得分:0)

您应该将整个catch块放入while语句中:

while(retryCount < MAX_RETRY && !success)
{
   try
   {
      //do stuff , calling web service
      success = true;
   }
   catch
   {
      retryCount++
      success = false;
   }
}