简体   繁体   English

试试后终于没有打电话了

[英]finally not called after try

For some reason within my console application I cannot get my finally block to run. 出于某种原因,在我的控制台应用程序中,我无法运行我的finally块。 I was writing this code to test how the finally block works so it is very simple: 我正在编写此代码来测试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();
    }
}

At first I had the problem described here but then I tried to run the program outside Visual Studio I got a "Program has stopped responding" error. 起初我遇到了这里描述问题,但后来我尝试在Visual Studio外部运行程序我得到了“程序已停止响应”错误。

Because you do not have a top level exception handler, the .Net runtime is catching the exception for you and aborting the program before the finally has a chance to run. 因为您没有顶级异常处理程序,所以.Net运行时正在为您捕获异常并在最终有机会运行之前中止该程序。 This illustrates the point: 这说明了这一点:

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

With this code, the exception is now handled a try...catch higher up in the calling chain (it just happens to be in the same method), so the embedded finally will be executed. 使用这段代码,异常现在处理了一个try ...在调用链中捕获更高的位置(它恰好在同一个方法中),因此最终将执行嵌入式。 The catch need not be in the same function where the exception is being raised, it can be anywhere in the calling chain. catch不需要在引发异常的同一函数中,它可以在调用链中的任何位置。

Edit: initially it may seem uncertain when and where an exception will be caught by your program. 编辑:最初可能看起来不确定您的程序将捕获异常的时间和地点。 But think about the boundaries of your application, where the outside world interacts with your code - normally they are limited and well defined. 但请考虑应用程序的界限,外部世界与您的代码交互 - 通常它们是有限的并且定义良好。 So for a console application, the boundary is the Main method, and this is where you can put the top level exception handler. 因此,对于控制台应用程序,边界是Main方法,这是您可以放置​​顶级异常处理程序的地方。 For a Web forms application, the boundary includes things like button click events (the user is interacting with your UI), so you could have exception handlers in there too. 对于Web表单应用程序,边界包括按钮单击事件(用户正在与UI交互)之类的内容,因此您也可以在其中使用异常处理程序。 For a class library the boundary is generally the boundary of the application that calls the library, not the library itself. 对于类库,边界通常是调用库的应用程序的边界,而不是库本身。 So do not catch exceptions in the library (unless you can sensibly recover from them), but let them bubble up to the calling application instead. 所以不要在库中捕获异常(除非你可以明智地从它们中恢复),但是让它们冒泡到调用应用程序。

In a larger program this would not be a problem as the DevideByZero exception would "bubble-up" and would hopefully be dealt with somewhere else. 在一个更大的程序中,这不会是一个问题,因为DevideByZero异常会“冒泡”并希望在其他地方处理。 Because this is in the main method, the exception has no where to go. 因为这是main方法,所以例外无处可去。 This causes the problem you see... 这会导致你看到的问题......

So the following would do as you expect 所以以下内容可以按照您的预期进行

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

I hope this helps. 我希望这有帮助。

Wanted to add my own findings here as the behavior here is certainly strange - and as such, the accepted answer is not entirely correct. 想在这里添加我自己的发现,因为这里的行为肯定很奇怪 - 因此,接受的答案并不完全正确。

Given the following sample: 鉴于以下示例:

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

The finally block is actually executed IF we choose to CANCEL out of the Windows Error Reporting Dialog, as such: 如果我们选择从Windows错误报告对话框中取消,则实际执行finally块,如下所示:

Windows错误报告正在进行中 完成后的控制台

HOWEVER, if we allow the Windows Error Reporting Dialog to "complete", so we get the option to "Debug" or "Close Program", then the finally block is NOT executed. 但是,如果我们允许Windows错误报告对话框“完成”,那么我们可以选择“调试”或“关闭程序”,然后不执行finally块。

在此输入图像描述 在此输入图像描述


Which to me indicates that the .NET Runtime WILL actually run all finally blocks, regardless of experiencing a "Unhandled top level Exception", and that what's preventing it from doing so is actually Windows (if you select "Close Program") or the Visual Studio Debugger (if you select "Debug" or is starting with the debugger attached)... As they kill the process before the Runtime as a chance to proceed. 对我来说,表明.NET Runtime将实际运行所有finally块,无论是否遇到“未处理的顶级异常”,并且阻止它这样做的实际上是Windows(如果选择“关闭程序”)或Visual Studio Debugger(如果您选择“Debug”或者正在启动附加的调试器)......因为他们在运行时之前杀死进程作为继续进行的机会。

Any thoughts? 有什么想法吗?

You still need a catch to capture the exception throwing: 你仍然需要一个捕获来捕获异常抛出:

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

This exception is causing the application to crash, and the exception is unhandled therefore terminating the application. 此异常导致应用程序崩溃,并且异常未处理因此终止应用程序。

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

Usually, when an unhandled exception ends an application, whether or not the finally block is run is not important. 通常,当未处理的异常结束应用程序时,无论finally块是否运行都不重要。 However, if you have statements in a finally block that must be run even in that situation, one solution is to add a catch block to the try-finally statement. 但是,如果在finally块中有语句,即使在这种情况下也必须运行,一种解决方案是在try-finally语句中添加一个catch块。

您需要分离调试器(例如,在发布模式下运行您的应用程序),请参阅以下(相关)问题以获取更多详细信息: 最终在使用F5时似乎无法在C#控制台应用程序中执行

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM