finally not called after try
Asked Answered
D

5

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.

Decuple answered 28/8, 2012 at 15:59 Comment(8)
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?Ly
Try taking out the ReadLine and run it in a command prompt outside Visual Studio. What happens then ?Ungual
I've tried that. It acts the same.Decuple
See this: #3422238Enthrall
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.Philbin
..I am using Visual Stusio 2010, .NET 4.0.Philbin
@Philbin that must happen when you run the executable because the debugger will not allow you to continue. Of course, I'm using 2008 sooo..Incorporeal
@carny666: yes, I am running the executable directly, or starting it from VS using Ctrl+F5 (no debugger)Philbin
P
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?

Pandemonium answered 28/8, 2019 at 10:3 Comment(1)
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.Decuple
R
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.

Roadster answered 28/8, 2012 at 16:9 Comment(5)
+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.Hindermost
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?Decuple
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...Pyaemia
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)Decuple
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.Distraction
P
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?

Pandemonium answered 28/8, 2019 at 10:3 Comment(1)
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.Decuple
P
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.

Pyaemia answered 28/8, 2012 at 16:7 Comment(0)
L
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.

Laurasia answered 28/8, 2012 at 16:1 Comment(4)
No because I'm trying to use try-finally: msdn.microsoft.com/en-us/library/zwc8s4fz%28v=vs.71%29.aspxDecuple
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...Pyaemia
@Incorporeal 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: #3422238 application-while-using-f5Canady
@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.Laurasia
C
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

Canady answered 28/8, 2012 at 16:10 Comment(1)
I actually mention this issue and reference that question in my question. I've tried running it outside the debugger.Decuple

© 2022 - 2024 — McMap. All rights reserved.