In C# Will the Finally Block Be Executed in a Try, Catch, Finally If an Unhandled Exception Is Thrown

Exception in catch block means the finally block never executes?

What and why it happens

The result depends on what button you click when the program crashes. If you're slow, the Windows Error Reporting (WER) dialog will show "Debug" and "Close program". If you press the "Close program" button, the program is terminated by the operationg system without any chance of writing something else to console.

Screenshot: close program

If you're fast enough to hit the "Cancel" button, then the Windows Error Reporting part will be cancelled and control goes back to your program. It will then write "Carrot" to the Console.

Screenshot: cancel

Therefore, this is not a .NET issue but it's a matter on how Windows reacts to exception dispatching.

How to get control over it

To disable the WER dialog, you can use WerAddExcludedApplication . To get rid of the Debug dialog, you can use SetErrorMode.

Please make yourself familiar with the disadvantages of using those methods. Read Raymond Chen's comments on WerAddExcludedApplication and check whether SetThreadErrorMode might be in favor.

Your code may then look like this:

using System;
using System.Runtime.InteropServices;

namespace ExceptionInCatch
{
class Program
{
[DllImport("wer.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern int WerAddExcludedApplication(String pwzExeName, bool bAllUsers);

[Flags]
public enum ErrorModes : uint
{
SYSTEM_DEFAULT = 0x0,
SEM_FAILCRITICALERRORS = 0x0001,
SEM_NOALIGNMENTFAULTEXCEPT = 0x0004,
SEM_NOGPFAULTERRORBOX = 0x0002,
SEM_NOOPENFILEERRORBOX = 0x8000,
SEM_NONE = SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX
}

[DllImport("kernel32.dll")]
static extern ErrorModes SetErrorMode(ErrorModes uMode);

public static void Main(string[] args)
{
var executableName = AppDomain.CurrentDomain.FriendlyName;
WerAddExcludedApplication(executableName, false);
SetErrorMode(ErrorModes.SEM_NONE);
try
{
throw new Exception("Apple");
}
catch (Exception ex)
{
throw new Exception("Banana");
}
finally
{
// This line will now execute
Console.WriteLine("Carrot");
}
}
}
}

Why finally block may not execute when exception is thrown?

You're assumptions are incorrect (sometimes) https://dotnetfiddle.net/hjqmOS

try-finally (C# Reference)

By using a finally block, you can clean up any resources that are
allocated in a try block, and you can run code even if an exception
occurs in the try block. Typically, the statements of a finally block
run when control leaves a try statement. The transfer of control can
occur as a result of normal execution, of execution of a break,
continue, goto, or return statement, or of propagation of an exception
out of the try statement.

There are cases when it doesn't run though

Within a handled exception, the associated finally block is guaranteed
to be run. However, if the exception is unhandled, execution of the
finally block is dependent on how the exception unwind operation is
triggered
. That, in turn, is dependent on how your computer is set up.

Here is the important part

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.
Alternatively, you can catch the exception that might be thrown in the
try block of a try-finally statement higher up the call stack.

Exception Handling in c# - try catch finally

In really simple terms, these are what try-catch-finally blocks do:

Try

The place where you'd put potentially problematic code. If an exception is generated, an exception will be thrown.

Catch

Catch is the ONLY block where an exception will be caught. Hence the name. So when an exception is thrown, if you want to ensure the program doesn't 'hang', you must catch the exception.

Finally

Do your cleanup. If, say, you have some array in your try block and you want to clean it up in case of an exception, this is the place to do it.

Try-Finally

The documentation says:

Within a handled exception, the associated finally block is guaranteed to be run. However, if the exception is unhandled, execution of the finally block is dependent on how the exception unwind operation is triggered. That, in turn, is dependent on how your computer is set up.

Meaning, if you don't catch your exception, it depends on the situation whether finally is run.

So, with that in mind, let's look at your first code block.

static void Main(string[] args)
{
int x = 0;
try
{
int divide = 12 / x;
}
finally
{
Console.WriteLine("I am finally block");
}
Console.ReadLine();
}

You're attempting to do a divide by zero which generates an exception. But there's no place for it to be 'caught', so the program hangs:

enter image description here

So if you add a catch block here, now it will allow for smooth sailing and go to your finally as well.

try
{
int divide = 12 / x;
}
catch (Exception ex)
{
Console.WriteLine("Oops. Division by Zero.");
}
finally
{
Console.WriteLine("I am finally block");
}

Now let's take your second code snippet. I'm going to do a small modification and flip the order of two lines of code inside the catch.

static void Main(string[] args)
{
int x = 0;
try
{
int divide = 12 / x;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
int divide = 12 / x;
}
finally
{
Console.WriteLine("I am finally block");
}
Console.ReadLine();
}

Now, the catch block catches the exception thrown by the first illegal division and prints a message. But then there's a second illegal division inside the catch, and there's no catch for that thrown exception so the program hangs.

So if you modify it to have a second try-catch inside the first catch like so:

static void Main(string[] args)
{
int x = 0;
try
{
int divide = 12 / x;
}
catch (Exception ex)
{
try
{
Console.WriteLine(ex.Message);
int divide = 12 / x;
}
catch (Exception ex2)
{
Console.WriteLine(ex2.Message);
}
}
finally
{
Console.WriteLine("I am finally block");
}
Console.ReadLine();
}

Now it will catch both exceptions and you're good to go.

So the idea is, if you have a try you should try to have a catch unless you can justify why you don't want one.

When is finally run if you throw an exception from the catch block?

It would be called after e is re-thrown (i.e. after the catch block is executed)

editing this 7 years later - one important note is that if e is not caught by a try/catch block further up the call stack or handled by a global exception handler, then the finally block may never execute at all.

C# exception handling finally block before catch block

In your first code, the reason that the finally (A) runs before the catch (B) is because when the exception is thrown, you exit the inner block (causing the finally to run) before the outer block's catch comes into play. Consider this code:

private void TestTryCatchFinally()
{
try
{
Debug.WriteLine("Start Outer Try");
try
{
Debug.WriteLine("Start Inner Try");
throw new Exception("Exception from inner try");
Debug.WriteLine("End of Inner Try - never reaced");
}
//remove this catch block for second test
catch (Exception)
{
Debug.WriteLine("In inner catch");
}
//end of code to remove
finally
{
Debug.WriteLine("In Inner Finally");
}
}
catch (Exception)
{
Debug.WriteLine("In outer catch");
}
finally
{
Debug.WriteLine("In outer finally");
}
}

If I run this code, I get this output:

Start Outer Try
Start Inner Try
Exception thrown: 'System.Exception' in MyTestApp.exe
In inner catch
In Inner Finally
In outer finally

Which is what you expect. But, if I remove the inner catch block (as noted in the code), I get this output:

Start Outer Try
Start Inner Try
Exception thrown: 'System.Exception' in MyTestApp.exe
In Inner Finally
In outer catch
In outer finally

In this case, as soon as execution exits the inner try block, the finally code executes. Then the outer catch block has it's turn.

What happens if a finally block throws an exception?

If a finally block throws an exception what exactly happens ?

That exception propagates out and up, and will (can) be handled at a higher level.

Your finally block will not be completed beyond the point where the exception is thrown.

If the finally block was executing during the handling of an earlier exception then that first exception is lost.

C# 4 Language Specification § 8.9.5: If the finally block throws another exception, processing of the current exception is terminated.

Finally block does not execute as Microsoft say in it's Doc

Check it here:

https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/try-finally

Within a handled exception, the associated finally block is guaranteed to be run. However, if the exception is unhandled, execution of the finally block is dependent on how the exception unwind operation is triggered. That, in turn, is dependent on how your computer is set up.

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. Alternatively, you can catch the exception that might be thrown in the try block of a try-finally statement higher up the call stack. That is, you can catch the exception in the method that calls the method that contains the try-finally statement, or in the method that calls that method, or in any method in the call stack. If the exception is not caught, execution of the finally block depends on whether the operating system chooses to trigger an exception unwind operation.

When is this usually?

If the exception is not caught, execution of the finally block depends on whether the operating system chooses to trigger an exception unwind operation.

Exception unwind

When we enclose a block of code with a try statement compiler creates a step to store current context of the CPU in current stack frame with program counter pointed to start of catch block. If the CPU encounters any error it retrieves the context from stack an program counter jumps to catch statement.

Conditions when finally does not execute in a .net try..finally block

Some examples:

  • StackOverflowException
  • ExecutionEngineException
  • Application exit


Related Topics



Leave a reply



Submit