【问题标题】:Resuming execution of code after exception is thrown and caught抛出并捕获异常后恢复执行代码
【发布时间】:2011-03-01 18:13:29
【问题描述】:

抛出异常后如何恢复代码执行?

以如下代码为例:

namespace ConsoleApplication1
{
    public class Test
    {
        public void s()
        {
            throw new NotSupportedException();
            string @class = "" ;
            Console.WriteLine(@class);
            Console.ReadLine();
        }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            try
            {
                new Test().s();
            }
            catch (ArgumentException x)
            {
            }
            catch (Exception ex)
            {
            }
        }
    }
}

单步执行时捕获异常后,程序将停止运行。我怎么还能继续执行?

编辑:我的具体意思是 Console.WriteLine(@class);似乎没有被击中,因为当我在调试模式下运行它时,程序退出调试模式。我想跑到这条线停下来。

谢谢

【问题讨论】:

  • 基于上面的代码,如果抛出异常,适当的catch块会拦截它。在 catch 块之后的任何语句都会被执行!!!
  • 听起来你想要 C# 版本的 BASIC 的 ON ERROR RESUME NEXT

标签: c# exception exception-handling


【解决方案1】:

好吧,catch 块之后没有任何代码,所以程序将停止运行。不知道你想做什么。

以下应该证明程序不会在catch 块之后简单地“停止”。如果有代码要执行,它将在catch块之后执行代码:

static void Main(string[] args)
{
    try
    {
        new Test().s();
    }
    catch (ArgumentException x)
    {
        Console.WriteLine("ArgumentException caught!");
    }
    catch (Exception ex) 
    { 
        Console.WriteLine("Exception caught!");
    }

    Console.WriteLine("I am some code that's running after the exception!");
}

代码将根据捕获的异常打印适当的字符串。然后,它会在最后打印I am some code that's running after the exception!

更新

在您的编辑中,您问为什么Console.WriteLine(@class); 似乎没有被击中。原因是您明确s() 方法的第一行抛出异常;随后的任何内容都将被忽略。当遇到异常时,执行停止并且异常向上传播到调用堆栈,直到适当的处理程序可以处理它(这可能是对应于 trycatch 块,它将相关语句包装在同一方法中, 或者它可能是一个catch 块进一步向上调用堆栈。如果没有找到合适的处理程序,程序将终止堆栈跟踪[至少在Java中-不确定在C#中是否发生同样的情况]。

如果您想点击Console.WriteLine 行,那么您不应该在方法的开头显式抛出异常。

【讨论】:

    【解决方案2】:

    听起来您想要可恢复的异常。 C# 不执行可恢复异常,我怀疑 CLR 是否支持它们。

    如果/当调用环境中的某些内容(参数、对象状态、全局状态)使函数的操作不可能或无效时,抛出异常的目的是中止函数和整个操作(调用堆栈)。例如,将零参数传递给需要将数量除以该参数的函数。除以零不会产生有意义的结果,如果这是函数的唯一目的,那么函数也不能返回有意义的结果。所以,抛出一个异常。这将导致执行跳转到最近的 catch 或最终阻塞调用堆栈。没有返回到引发异常的函数。

    如果您想在调试器中单步执行代码以跟踪 Console.WriteLine() 调用,则需要从代码中删除 throw new NotSupportedException() 行并重新编译。

    【讨论】:

      【解决方案3】:

      如果您担心方法中会抛出异常但又希望方法继续执行,请在方法中添加错误处理程序。

      class Test 
      { 
          public void s() 
          { 
              try
                {
                    // Code that may throw an exception
                    throw new NotSupportedException();
                } 
                catch(Exception ex)
                {
                    // Handle the exception - log?, reset some values?
                }
                string @class = "" ; 
                Console.WriteLine(@class); 
                Console.ReadLine(); 
          } 
      } 
      

      您还可以返回一个布尔值或其他值来指示状态。

      【讨论】:

        【解决方案4】:

        免责声明:我并不是建议您实际这样做。

        您可以使用以下代码模仿旧的 VB 样式 On Error Resume Next。

        public static class ControlFlow
        {
          public static Exception ResumeOnError(Action action)
          {
            try
            {
              action();
              return null;
            }
            catch (Exception caught)
            { 
              return caught;
            }
          }
        }
        

        然后它可以像下面这样使用。

        public static void Main()
        {
          ControlFlow.ResumeOnError(() => { throw new NotSupportedException(); });
          ControlFlow.ResumeOnError(() => { Console.WriteLine(); });
          ControlFlow.ResumeOnError(() => { Console.ReadLine(); });
        }
        

        【讨论】:

          【解决方案5】:

          我整理了一些简单的代码来捕获在 catch 块中抛出的异常:

          try
          {
              //do code here
          }
          catch (Exception ex)
          {
              try { SomeMethod1(); }
              catch { }
          
              try { SomeMethod2(); }
              catch { }
          
              try { SomeMethod3(); }
              catch { }
          }
          finally
          {
              //cleanup goes here
          }
          

          【讨论】:

          • 无论是否抛出异常,finally块都会执行
          【解决方案6】:

          执行仍在继续,但捕获异常后没有代码。如果您想重复调用 s,请考虑将 try/catch 块包装在 while 循环中。

          【讨论】:

            【解决方案7】:

            程序停止运行,因为在 Main() 方法中没有要执行的以下代码!您可以将以下行添加到您的代码中,以保持程序运行,直到有控制台输入:

            Console.ReadLine();
            

            【讨论】:

              【解决方案8】:

              对于该代码,您不能。如果你把任务分成更小的块,你可以在下一个块继续。但通常情况下,使用与异常不同的机制来报告非致命错误会更容易,例如返回是否继续的回调函数。

              【讨论】:

                【解决方案9】:

                您可以在调试中使用“跨步”功能在每次运行的基础上实现此目的。

                【讨论】:

                  【解决方案10】:
                  public static void Main()
                  {
                      for (int j = 0; j <= 100000; j++)
                      {
                          try
                          {
                                  // TODO: Application logic...
                          }
                          catch
                          {
                                  System.Threading.Thread.Sleep(1000);
                          }
                      }
                  }
                  

                  【讨论】:

                  • 它会等待一秒钟然后再次尝试执行,前提是错误是暂时的
                  • 除非你的“应用程序逻辑”无论如何都会重复 100000 次。
                  • 虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。
                  • 如果您将System.Threading.Thread.Sleep(1000); 更改为简单的Main(),您可能会遇到一些问题
                  猜你喜欢
                  • 1970-01-01
                  • 2018-11-22
                  • 1970-01-01
                  • 2012-09-15
                  • 2018-11-18
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-09-02
                  • 1970-01-01
                  相关资源
                  最近更新 更多