【问题标题】:Is it possible to execute the code in the try block again after an exception in caught in catch block?在 catch 块中捕获异常后,是否可以再次执行 try 块中的代码?
【发布时间】:2012-02-14 05:10:04
【问题描述】:

我想在捕获到异常后再次执行 try 块中的代码。这有可能吗?

例如:

try
{
    //execute some code
}
catch(Exception e)
{
}

如果捕获到异常,我想再次进入 try 块以“执行一些代码”并再次尝试执行它。

【问题讨论】:

标签: c# .net exception exception-handling


【解决方案1】:

把它放在一个循环中。可能会围绕一个布尔标志进行 while 循环,以控制您最终想要退出的时间。

bool tryAgain = true;
while(tryAgain){
  try{
    // execute some code;
    // Maybe set tryAgain = false;
  }catch(Exception e){
    // Or maybe set tryAgain = false; here, depending upon the exception, or saved details from within the try.
  }
}

请注意避免无限循环。

更好的方法可能是将您的“一些代码”放在它自己的方法中,然后您可以根据需要从 try 和 catch 中调用该方法。

【讨论】:

    【解决方案2】:

    如果你将你的块包装在一个方法中,你可以递归调用它

    void MyMethod(type arg1, type arg2, int retryNumber = 0)
    {
        try
        {
            ...
        }
        catch(Exception e)
        {
            if (retryNumber < maxRetryNumber)
                MyMethod(arg1, arg2, retryNumber+1)
            else
                throw;
        }
    }
    

    或者你可以循环执行。

    int retries = 0;
    
    while(true)
    {
        try
        {
            ...
            break; // exit the loop if code completes
        }
        catch(Exception e)
        {
            if (retries < maxRetries)
                retries++;
            else
                throw;
        }
    }
    

    【讨论】:

    • 然后你也可以因为没有端点而遇到stackoverflow。
    • 如果该函数返回某个值而不是 void 怎么办?
    【解决方案3】:
    int tryTimes = 0;
    while (tryTimes < 2) // set retry times you want
    {
        try
        {
            // do something with your retry code
            break; // if working properly, break here.
        }
        catch
        {
            // do nothing and just retry
        }
        finally
        {
            tryTimes++; // ensure whether exception or not, retry time++ here
        }
    }
    

    【讨论】:

    • 如果第二个try 失败,我想throwException 怎么办?我需要另一个catch 块吗?如果您能分享语法,将不胜感激。
    • 如果你想抛出异常,这可能很容易。只写 catch (Exception ex) { if (tryTimes == 2) throw ex; }
    【解决方案4】:
    【解决方案5】:

    还有另一种方法(尽管正如其他人提到的那样,并不推荐)。下面是一个使用文件下载重试以更紧密匹配 VB6 中 Ruby 中的 retry 关键字的示例。

    RetryLabel:
    
    try
    {
        downloadMgr.DownLoadFile("file:///server/file", "c:\\file");
        Console.WriteLine("File successfully downloaded");
    }
    catch (NetworkException ex)
    {
        if (ex.OkToRetry)
            goto RetryLabel;
    }
    

    【讨论】:

    • 似乎比递归或无限循环更清楚地解决这个特定问题。
    • 不幸的是,这正是您可能在这里完成的——无限循环。如果发生异常,并且没有采取任何措施来解决根本原因,则没有重试计数器等来停止循环。 ex.OkToRetry 检查可能是一个开始,但尚不清楚 truefalse 之间是否或在何处设置不同。
    • @ziesemer - 你的例子也可以这样说,它被接受为答案。
    【解决方案6】:

    ole goto 有什么问题?

     Start:
                try
                {
                    //try this
                }
                catch (Exception)
                {
    
                    Thread.Sleep(1000);
                    goto Start;
                }
    

    【讨论】:

    • 因为它们会导致意大利面条代码。见stackoverflow.com/questions/3517726/…
    • @Malky.Kid,如果你不重构,任何代码都会导致意大利面条代码。在一个地方有一个 goto 语句很好,实际上可能会清理你的代码..
    • @Malky.Kid 你的链接强化了我的回答。 "goto 在一些地方是合适的,比如跳出嵌套循环"
    【解决方案7】:

    这应该可行:

    count = 0;
    while (!done) {
      try{
        //execute some code;
        done = true;
      }
      catch(Exception e){
      // code
      count++;
      if (count > 1) { done = true; }
      }
    }
    

    【讨论】:

    • 为什么要使用标志,你在这里运行了一个 for 循环。所以使用 for 循环结构。
    【解决方案8】:

    我知道社区对 goto 的看法,但这是我会(并且确实)使用它的情况。我的一个应用程序运行一个填充 ObservableCollection 的 BackgroundWorker。当 BackgroundWorker 正在运行并且 ObservableCollection 正在被填充时,我允许通过 UI 执行一些其他功能,但我需要基于某个时间点上 ObservableCollection 的计数来建立一些逻辑。所以我这样做了:

    long resultCount;           
    try_again:
    try
    {
        //This statement sometimes fails because ocResultList is volatile
        //while the BackgroundWorker is running
    
        resultCount = <ClassName>.ocResultList.LongCount();
    }
    catch
    {
        goto try_again;
    }
    
    if(resultCount...)
    {
        //do something
    }
    

    完全符合我的要求 - 没有意大利面条代码

    【讨论】:

    • 欢迎来到 Stack Overflow!这个答案似乎与已经提供的其他建议的 goto 解决方案没有足够的不同。包括一个对您的情况有独特变化但不适用于该问题的答案通常对其他人没有帮助。
    猜你喜欢
    • 1970-01-01
    • 2019-11-11
    • 2023-03-20
    • 1970-01-01
    • 2020-12-11
    • 1970-01-01
    • 1970-01-01
    • 2011-01-11
    • 1970-01-01
    相关资源
    最近更新 更多