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.
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.
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:
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
Ef Core 2.1 Hasconversion on All Properties of Type Datetime
How to Ignore Get-Only Properties in JSON.Net Without Using JSONignore Attributes
How to Get a List of Installed Updates and Hotfixes
Accessing UI Controls in Task.Run with Async/Await on Winforms
Alternative to Findmimefromdata Method in Urlmon.Dll One Which Has More Mime Types
Update App.Config System.Net Setting at Runtime
Wpf Clickonce Dpi Awareness Per-Monitor V2
Questions About Entity Framework Context Lifetime
Set Environment Variables for a Process
Ghost-Borders ('Ringing') When Resizing in Gdi+
How to Create a Generic Class from a String in C#
Opening a "Known File Type" into Running Instance of Custom App - .Net