试试后终于没有打电话了

时间:2012-08-28 15:59:24

标签: c# exception-handling try-finally

由于某些原因,在我的控制台应用程序中,我无法运行finally块。我正在编写此代码来测试finally块的工作方式,因此非常简单:

static void Main()
{
    int i = 0;
    try
    {
        int j = 1 / i; // Generate a divide by 0 exception.
    }
    finally
    {

        Console.Out.WriteLine("Finished");
        Console.In.ReadLine();
    }
}

起初我有problem described here但后来我尝试在Visual Studio外部运行程序我得到了“程序已停止响应”错误。

5 个答案:

答案 0 :(得分:11)

因为您没有顶级异常处理程序,所以.Net运行时正在为您捕获异常并在最终有机会运行之前中止该程序。这说明了一点:

static void Main() 
{
  try
  {
      int i = 0;
      try
      {
         int j = 1 / i; // Generate a divide by 0 exception.
      }
      finally
      {
          Console.Out.WriteLine("Finished");
          Console.In.ReadLine();     
      }
  }
  catch (Exception ex)
  {
      Console.WriteLine(ex.ToString());
  }
}

使用这段代码,异常现在处理了一个try ...在调用链中捕获更高的位置(它恰好在同一个方法中),因此最终将执行嵌入式。 catch不需要在引发异常的同一函数中,它可以在调用链中的任何位置。

编辑:最初看起来可能无法确定您的程序何时以及何处捕获异常。但请考虑应用程序的界限,外部世界与您的代码交互 - 通常它们是有限的并且定义良好。因此,对于控制台应用程序,边界是Main方法,这是您可以放置​​顶级异常处理程序的地方。对于Web表单应用程序,边界包括按钮单击事件(用户正在与UI交互)之类的内容,因此您也可以在其中使用异常处理程序。对于类库,边界通常是调用库的应用程序的边界,而不是库本身。所以不要在库中捕获异常(除非你可以明智地从它们中恢复),而是让它们冒泡到调用应用程序。

答案 1 :(得分:2)

想在这里添加我自己的发现,因为这里的行为肯定很奇怪-因此,公认的答案并不完全正确。

给出以下示例:

static void Main(string[] args)
{
    try{
        throw new Exception("");
    } finally {
        Console.WriteLine("I am never called!");
        Console.ReadLine();
    }
}

如果我们选择从Windows错误报告对话框中取消,则finally块实际上会执行,例如:

Windows Error Reporting In Progress Console After Done

但是,如果我们允许Windows错误报告对话框“完成”,那么我们可以选择“调试”或“关闭程序”,则不会执行finally块。

enter image description here enter image description here


对我来说,这表明.NET运行时实际上将运行所有finally块,而不管是否遇到“未处理的顶级异常”,并且阻止这样做的实际上是Windows(如果选择“关闭程序”)或Visual Studio调试器(如果您选择“调试”,或者正在连接调试器启动)...因为它们会在运行时之前杀死进程,从而有机会继续。

有什么想法吗?

答案 2 :(得分:1)

在一个较大的程序中,这不会是一个问题,因为DevideByZero异常会“冒泡”并希望希望在其他地方处理。因为这是在main方法中,所以例外无处可去。这会导致你看到的问题...

所以以下内容会按预期进行

static void Main(string[] args)
{
    try
    {
        CatchTest();
    }
    catch (Exception)
    {

    }
}

private static void CatchTest()
{
    int i = 0;
    try
    {
        int j = 1 / i; // Generate a divide by 0 exception.    
    }
    finally
    {
        Console.Out.WriteLine("Finished");
        Console.In.ReadLine();
    }
}

我希望这会有所帮助。

答案 3 :(得分:0)

你仍然需要一个捕获来捕获异常抛出:

int i = 0;
        try
        {
            int j = 1 / i; // Generate a divide by 0 exception.
        }
        catch(Exception e)
        {
            Console.Out.WriteLine("Exception caught");
        }
        finally
        {

            Console.Out.WriteLine("Finished");
            Console.In.ReadLine();
        }

此异常导致应用程序崩溃,并且异常未处理,因此终止应用程序。

http://msdn.microsoft.com/en-us/library/zwc8s4fz(v=vs.100).aspx

  

通常,当未处理的异常结束应用程序时,无论finally块是否运行都不重要。但是,如果在finally块中有语句,即使在这种情况下也必须运行,一种解决方案是在try-finally语句中添加一个catch块。

答案 4 :(得分:0)

您需要分离调试器(例如,在发布模式下运行您的应用程序),请参阅以下(相关)问题以获取更多详细信息:finally doesn't seem to execute in C# console application while using F5