Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

finally not called after try

For some reason within my console application I cannot get my finally block to run. I was writing this code to test how the finally block works so it is very simple:

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.

like image 256
Fr33dan Avatar asked Aug 28 '12 15:08

Fr33dan


2 Answers

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. 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. The catch need not be in the same function where the exception is being raised, it can be anywhere in the calling chain.

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. 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. 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.

like image 153
Polyfun Avatar answered Sep 29 '22 09:09

Polyfun


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 Error Reporting In Progress Console After Done

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.

enter image description here enter image description here


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.

Any thoughts?

like image 45
Jens Avatar answered Sep 29 '22 09:09

Jens