5

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.

Mark Amery
  • 143,130
  • 81
  • 406
  • 459
Fr33dan
  • 4,227
  • 3
  • 35
  • 62
  • Hm, I'm not quite familar with C#, but you aren't catching the division by zero exception at all...maybe this is the error? – akluth Aug 28 '12 at 16:00
  • Try taking out the ReadLine and run it in a command prompt outside Visual Studio. What happens then ? – user957902 Aug 28 '12 at 16:04
  • I've tried that. It acts the same. – Fr33dan Aug 28 '12 at 16:05
  • 2
    See this: http://stackoverflow.com/questions/3421738/finally-doesnt-seem-to-execute-in-c-sharp-console-application-while-using-f5 – vpascoal Aug 28 '12 at 16:06
  • 1
    Works fine for me - I get the unhandled exception error box, I select 'Close the program' and then the code in the `finally` block runs - display `Finished` and wait for ENTER to be pressed. – MiMo Aug 28 '12 at 16:07
  • ..I am using Visual Stusio 2010, .NET 4.0. – MiMo Aug 28 '12 at 16:08
  • @MiMo that must happen when you run the executable because the debugger will not allow you to continue. Of course, I'm using 2008 sooo.. – carny666 Aug 28 '12 at 16:09
  • @carny666: yes, I am running the executable directly, or starting it from VS using Ctrl+F5 (no debugger) – MiMo Aug 28 '12 at 16:29

5 Answers5

13

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.

Polyfun
  • 9,479
  • 4
  • 31
  • 39
  • 1
    +1 Thank you for explaining that you do need a `catch` block, but unlike other answers, outside of the scope of the `try-finally` block in question. – Steve Guidi Aug 28 '12 at 16:13
  • I understand, the exception is passed to the higher level before the finally is called. Since there is no higher level the program halts and quits before the finally. But does this mean I can never be sure that my finally will run since I may not know the status of the calling chain? – Fr33dan Aug 28 '12 at 16:29
  • No. Finallys will always run. The only case they don't is when you have a major problem with your code (unhandled exception which is not caught anywhere). The runtime does not know what to do with the exception so the code cannot proceed... – MoonKnight Aug 28 '12 at 16:33
  • Right so if I'm writing a single method I cannot be sure exceptions thrown within the try will eventually be caught by something. So in such a context I cannot guarantee my finally will be called (unless I catch the exceptions myself) – Fr33dan Aug 28 '12 at 16:45
  • 1
    Hmm. Some docs explaining *precisely* what happens, in what order, when there's an uncaught exception in `Main()` would improve this answer - the behavior shown here is frankly pretty weird and unlike any other language I've used. I can't find any such docs, though. – Mark Amery Nov 05 '17 at 20:32
3

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?

Jens
  • 3,353
  • 1
  • 23
  • 27
  • I think you are entirely correct in that it is the Windows Error Reporting stopping and killing the program that prevents the finally from being called. One crucial key to making this discovery is that Windows 10 handles the exceptions differently than Windows 7. I tried this on my development machine that is still running Win7 when WER is canceled the program remains frozen and greyed out. On a nearby Win10 machine it works like you show. My guess is WER halts execution and on Win7 never resumes it while on Win10 the program is let go after WER detaches. – Fr33dan Aug 28 '19 at 15:49
1

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. Because this is in the main method, the exception has no where to go. 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.

MoonKnight
  • 23,214
  • 40
  • 145
  • 277
0

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

Usually, when an unhandled exception ends an application, whether or not the finally block is run is not important. 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.

Tom
  • 2,360
  • 21
  • 15
  • No because I'm trying to use try-finally: http://msdn.microsoft.com/en-us/library/zwc8s4fz%28v=vs.71%29.aspx – Fr33dan Aug 28 '12 at 16:01
  • No. This is not right. The finally block will always get called as long as the exception has somewhere to go. In this case it doesn't... – MoonKnight Aug 28 '12 at 16:11
  • @carny666 it's happening because he's running it in a debugger, if he runs it in release mode the finally will be executed. See this question for more details: http://stackoverflow.com/questions/3421738/finally-doesnt-seem-to-execute-in-c-sharp-console- application-while-using-f5 – Kiril Aug 28 '12 at 16:11
  • @killercam - Yes, and that is why his program is crashing and the finally block is never called. If he had another surrounding try/catch it will not crash and finally will be called. – Tom Aug 28 '12 at 16:13
0

You need to detach the debugger (e.g. run your application in Release mode), see the following (related) question for more details: finally doesn't seem to execute in C# console application while using F5

Community
  • 1
  • 1
Kiril
  • 39,672
  • 31
  • 167
  • 226
  • I actually mention this issue and reference that question in my question. I've tried running it outside the debugger. – Fr33dan Aug 28 '12 at 16:25