Evasive exceptions and "a function evaluation has timed out" - c#

Background
In my utilities library (Shd.dll) I have a class called AsyncOperation. To put it simply, it's a base class for types that encapsulate a potentially long running operation, executes it on a background thread, and it supports pause/resume, cancellation and progress reporting. (It's like a BackgroundWorker, just knows more things.)
In the user code you can use it like this:
class MyOperation : AsyncOperation
{
public MyOperation() : base(null, AsyncOperationOptions.Cancelable | AsyncOperationOptions.Pausable) {}
protected override void RunOperation(AsyncOperationState operationState, object userState)
{
...
operationState.ThrowIfCancelled();
}
}
var op = new MyOperation();
op.Start();
...
op.Cancel();
operationState.ThrowIfCancelled() does exactly what its name suggests: if Cancel() was called earlier by another thread, it throws an internal exception (AsyncOperationCancelException), which is then handled by the AsyncOperation type, like this:
private void _DoExecute(object state)
{
// note that this method is already executed on the background thread
...
try
{
operationDelegate.DynamicInvoke(args); // this is where RunOperation() is called
}
catch(System.Reflection.TargetInvocationException tiex)
{
Exception inner = tiex.InnerException;
var cancelException = inner as AsyncOperationCancelException;
if(cancelException != null)
{
// the operation was cancelled
...
}
else
{
// the operation faulted
...
}
...
}
...
}
This works perfectly. Or so I thought for the past year, while I was using this in numerous scenarios.
The actual problem
I'm building a class that uses System.Net.WebClient to upload potentially large number of files via FTP. This class is built using the AsyncOperation base class as described above.
For accurate progress reports, I use WebClient.UploadFileAsync(), which complicates the code, but the relevant parts look like this:
private ManualResetEventSlim completedEvent = new ManualResetEventSlim(false);
private void WebClient_UploadProgressChanged(object sender, UploadProgressChangedEventArgs e)
{
...
if (OperationState.IsCancellationRequested)
{
_GetCurrentWebClient().CancelAsync();
}
}
private void WebClient_UploadFileCompleted(object sender, UploadFileCompletedEventArgs e)
{
...
_UploadNextFile();
}
private void _UploadNextFile()
{
if (OperationState.IsCancellationRequested || ...)
{
this.completedEvent.Set();
return;
}
...
}
protected override void RunOperation(AsyncOperationState operationState, object userState)
{
...
_UploadNextFile();
this.completedEvent.Wait();
operationState.ThrowIfCancelled(); // crash
...
}
As you can see, I marked the line where the crash occurs. What exactly happens is that when execution hits that line (I put a break point right over it, so I know this is the exact line), Visual Studio 2010 freezes for about 15 seconds, and then the next thing I see is the source code of AsyncOperationState.ThrowIfCancelled():
public void ThrowIfCancelled()
{
if(IsCancellationRequested)
{
throw new AsyncOperationCancelException();
}
} // this is the line the debugger highlights: "An exception of type AsyncOperationCancelException' occured in Shd.dll but was unhandled by user code."
I tried putting breakpoints to where the exception should have been caught, but the execution never reaches that catch {} block.
The other weird this is that at the end it also writes the following: "Function evaluation disabled because a previous function evaluation timed out." I Googled this problem, and tried everything that was suggested (disabled implicit property evaluation, removed all breakpoints), but nothing helped so far.
Here are two screenshots that illustrate the problem:
http://dl.dropbox.com/u/17147594/vsd1.png
http://dl.dropbox.com/u/17147594/vsd2.png
I'm using .NET 4.0. Any help would be very much appreciated.

When the Visual Studio debugger is attached to an application, it gets notified whenever an exception is thrown, before the running code gets the chance to handle it. This is called a first-chance exception, and VS can be configured to break execution when a certain exception type is thrown.
You can specify debugger behavior for each exception type separately using the Exceptions window (Debug menu). By default, all exceptions have the "User-unhandled" checkbox checked, meaning that only unhandled exceptions will break execution. Setting the "Thrown" checkbox for a certain exception type forces VS to break execution even if the exception will be handled, but only for that exception type (not for derived types). If a handler exists, once you resume execution (by pressing F5), the exception will be caught normally.
I would guess that your custom exception was added to the list of exceptions in the Exceptions window (which you can check by using the Find button inside the window).
[Edit]
According to my tests, it also happens when DynamicInvoke is used in .NET 4, regardless of the Exceptions window setting. Yesterday I was using VS2008 and I couldn't reproduce it, but it does seem like odd behavior now.
This is the test I tried (sorry for the brief formatting, but it's fairly simple):
Action<int> a = i => { throw new ArgumentException(); };
// When the following code is executed, VS2010 debugger
// will break on the `ArgumentException` above
// but ONLY if the target is .NET 4 (3.5 and lower don't break)
try { a.DynamicInvoke(5); }
catch (Exception ex)
{ }
// this doesn't break
try { a.Invoke(5); }
catch (Exception ex)
{ }
// neither does this
try { a(5); }
catch (Exception ex)
{ }
My only guess is that exception handling done inside InvokeMethodFast (which is an InternalCall method) has somehow changed. DynamicInvoke code has changed between versions 4 and prior, but there is nothing which would indicate why VS2010 debugger is unable to see that there is an exception handler inside that method call.

“a function evaluation has timed out”
You don't have a real problem, this is a debugger artifact. It is triggered by the way the debugger evaluates watch expressions. When you start a .NET program with the debugger attached, the program will have a dedicated thread, solely for use by the debugger. Whenever the debugger needs to evaluate a watch expression, it uses that thread to execute the expression code. The result is then displayed in the watch window.
Which works very well and gives the debugger a lot of capabilities. Including calling a method in your program when a breakpoint is active. Rather necessary, a lot of object values you'd be interested in are exposed as properties. Which are implemented as methods in the generated code.
That debugger thread can however cause trouble. An obvious case is where you try to evaluate a property that takes a lock. If you break execution at a stage where that lock is owned by another thread then the debugger thread is going to hit a brick wall. It trundles for a while, notices that the debugger thread isn't completing, then gives up and displays "a function evaluation has timed out" as the watch value. It also remembers that it failed, any watches you try later will produce "Function evaluation disabled because a previous function evaluation timed out". Necessarily so, the debugger thread is still stuck in a rut.
Similar kind of problem in your code. The probable scenario there is that the thread you need to get the operation completed got suspended by the debugger break. The only decent advice to give here is to be careful with your watch expressions.

If your try catch logic is running on a different thread than the code that actually throws the exception, then the catch block will never execute.
Consider the following sample:
class Program
{
static void Main(string[] args)
{
try
{
Thread thread = new Thread((s) =>
{
throw new Exception("Blah");
});
thread.Start();
}
catch (Exception ex)
{
Console.WriteLine("Exception caught: {0}", ex);
}
Console.ReadKey();
}
}
The catch block of course does not execute since the exception was thrown on a different thread.
I'm suspecting that you could be experiencing something similar. If you want your catch block to execute, it must be on the same thread that the error is being thrown on.
Good luck!

Related

Why Dispose is not called even with using-statement?

I have this console application (.NET Framework 4.5.2):
class Program
{
static void Main(string[] args)
{
using (var result = new Result())
{
result.Test();
}
}
}
public class Result : IDisposable
{
public void Test()
{
int a = 1;
int b = 1 / (a - 1);
}
public void Dispose()
{
Console.WriteLine("Dispose");
}
}
Why Dispose method is not called? A breakpoint is not hit in Dispose after the DivideByZero-exception and there is no output on the console (because the app exits).
As per MS Docs: try-finally (C# Reference)
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.
As you are not catching the DivideByZero exception and let it be unhandled, on your machine and setup it must be bringing down the application before any other line of code is run and therefore not running the finally block.
As #Evk has pointed out in below comment, if I run it without attaching debugger, it unwinds the exceptions correctly and executes the finally block. Learn something new everyday.
As per Eric Lippert's answer to Finally Block Not Running?
Think about how awful that situation is: something unexpected has
happened that no one ever wrote code to handle. Is the right thing to
do in that situation to run even more code, that was probably also not
built to handle this situation? Possibly not. Often the right thing to
do here is to not attempt to run the finally blocks because doing so
will make a bad situation even worse. You already know the process is
going down; put it out of its misery immediately.
In a scenario where an unhandled exception is going to take down the
process, anything can happen. It is implementation-defined what
happens in this case: whether the error is reported to Windows error
reporting, whether a debugger starts up, and so on. The CLR is
perfectly within its rights to attempt to run finally blocks, and is
also perfectly within its rights to fail fast. In this scenario all
bets are off; different implementations can choose to do different
things.

Environment.FailFast in c# application

I'd like to understand the Environment.FailFast rule in c# application. So , I made this code :
public static void Main()
{
string strInput = GetString();
Console.WriteLine(strInput);
Console.ReadKey();
}
private static string GetString()
{
Console.WriteLine("Get string");
string s = Console.ReadLine();
try
{
if (s == "Exit")
{
Environment.FailFast("Erreur fatale");
return s;
}
else
{
return s;
}
}
catch (Exception)
{
return "catch";
}
finally
{
s += "finally";
}
}
As I learned, the message are written to the Windows application event log and the application is terminated.
When I run the application and put Exit as a string :
The debbugger indicates an error :
I try to find the event log file, as indicated in msdn, but I don't find it
I don't understand why the application didn't shut down without throwing the exception? For the second point, How can I find the log file in my PC?
Environment.FailFast(string) exits the application immediately, without allowing any catch statements or finalizers to be run on the object.
You should only use this method if your application's state is at a point where it can never be recovered, and exiting the application is the only way to ensure something far worse than crashing does not happen. In your sample, using Environment.Exit with an exit code is more suitable, as it appears to be a graceful exit, rather than one forced through corrupt state.
In general, it is recommended to not use FailFast while the debugger is attached - this is documented in the System.Diagnostics.Assert class:
// However, in CLR v4, Environment.FailFast when a debugger is attached gives you an MDA
// saying you've hit a bug in the runtime or unsafe managed code, and this is most likely caused
// by heap corruption or a stack imbalance from COM Interop or P/Invoke. That extremely
// misleading error isn't right, and we can temporarily work around this by using Environment.Exit
// if a debugger is attached. The right fix is to plumb FailFast correctly through our native
// Watson code, adding in a TypeOfReportedError for fatal managed errors. We may want a contract-
// specific code path as well, using COR_E_CODECONTRACTFAILED.
Which means the exception you're seeing in Visual Studio is down to a bug in the CLR, and could be safely ignored.
Their work around is as follows:
if (Debugger.IsAttached)
Environment.Exit(COR_E_FAILFAST);
else
Environment.FailFast(message);
Which means that while running with the debugger attached, you won't get the Event Log message written, while in release you do.
I've reconstructed your problem with the following piece of code:
static void Main(string[] args)
{
try
{
Console.WriteLine("Foo");
Environment.FailFast("WOHO!");
}
finally { }
}
When running this under the debugger, I didn't see any exceptions registered either. Running this without the debugger (Ctrl + F5) makes the exception appear in the Event Viewer properly (see #aevitas answer or read this for why that happens):

C# - Application terminates unexpectedly without leaving traces

I have a simple C# application/game using SFML.Net that currently stops running / terminates within 1 or 2 seconds after being executed without any warning, exception, etc. whatsoever. Consider the following code:
public static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(OnUnhandledException);
--> The following two lines are run
Console.WriteLine("Hello");
Console.WriteLine("Please don't go...");
// Run the game
try
{
--> This line is reached
Game.Run();
}
catch (Exception e)
{
--> This line is never reached
Console.WriteLine(e.Message.ToString());
}
--> These lines are never reached
Console.WriteLine("Noone ever comes here, I feel so lonely... :(");
Console.ReadKey();
}
}
At this point you probably expect that something is wrong with the Game.Run() method. The odd thing is that the first line of the method is never reached according to the VS Debugger.
public static void Run()
{
try
{
--> Never reached
LoadContent();
// Do stuff here
while (window.IsOpen())
{
// The classic game loop
}
}
catch (Exception e)
{
--> Never reached
Console.WriteLine(e.Message.ToString());
Console.ReadKey();
}
}
My guess is that either:
You are getting an Access Violation Exception which cannot be caught.
OR
There is some other exception before you go into the Run method that is not handled. In order to verify that, make sure your debugger stops on first chance exceptions.
It would also be helpful if you specify:
How do you know that the first line is never reached? breakpoint? output?
What happens when you expect this function to be entered? does your application exist?
Are you debugging step by step?
My Guess is that the exception is being thrown by another thread. You cannot catch an exception thrown from another thread in the main thread. So your breakpoint in catch will never be hit. Btw did you try having a breakpoint in your UnhandledExceptionEventHandler method OnUnhandledException? That is where all unhandled exceptions go! Hope this helps.
You can get all called functions stack in your application until the termination point with the Runtime Flow tool (30 day trial, developed by me) and find what actually happens.
I came back to this after a couple of months and realized how silly my mistake was. Apparently unmanaged code debugging wasn't enabled by default (this was my first time using VS2012), and this exception was being thrown from the base C++ libs of SFML.
For those who don't know, to enable unmanaged debugging:
Project > Properties > Debug > Select "Enable unmanaged code debugging"

InvokeRequired Exception Handling

I noticed a few strange behaviors in a Windows Forms scenario which involves threads and UI, so, naturally, this means making use of the InvokeRequired property. The situation: my application makes use of a thread to do some work and the thread sends an event into the UI. The UI displays a message based on an Internationalization system which consists of a dictionary with keys. The I18N system cannot find a key in the dictionary and crashes.
Notes: application is in Debug Mode and I have a try-catch over the entire "Application.Run();" back in Program.cs. However, that try-catch is not reached, as what I will discuss here is based on inner Exception handling, but I mentioned it just in case.
So now here comes the fun parts:
Why, for the life of me, does Visual Studio "censor" exception information from me? In the code below, you will see on the if (InvokeRequired) branch, a try-catch. I log the exception. ex.InnerException is NULL and the provided ex.StackTrace is anemic (only 1 step in it). Now if I comment the try-catch and simply let it crash via the Debugger, I get a much ampler stack trace. Why is that?
To make things worse, neither of the two stack traces versions contain any information about the i18N crash. They just say "The given key was not present in the dictionary." and give me a stack trace up to the Invoke declaration.
On the else branch (that is, InvokeRequired == false), if I put a try-catch, I can successfully catch my Exception back to the i18n system. As you can see, I tried to send my exception with InnerException back to the InvokeRequired == true branch. However, even so, InnerException stays NULL there and I cannot access my i18N error.
I am puzzled by all these things and maybe somebody can help shed some light over here. If you got really strong lanterns that is.
Here is the function's code.
private delegate void AddMessageToConsole_DELEGATE (frmMainPresenter.PresenterMessages message);
private void AddMessageToConsole (frmMainPresenter.PresenterMessages message)
{
if (InvokeRequired)
{ //Catching any errors that occur inside the invoked function.
try { Invoke(new AddMessageToConsole_DELEGATE(AddMessageToConsole), message); }
catch (Exception ex) { MSASession.ErrorLogger.Log(ex); }
//Invoke(new AddMessageToConsole_DELEGATE(AddMessageToConsole), message);
}
else
{
string message_text = ""; //Message that will be displayed in the Console / written in the Log.
try
{
message_text = I18N.GetTranslatedText(message)
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
txtConsole.AppendText(message_text);
}
}
Yes, this is built-in behavior for Control.Invoke(). It only marshals the deepest nested InnerException back to the caller. Not so sure why they did this, beyond avoiding reporting exceptions that were raised by the marshaling code and would confuzzle the reader. It was done explicitly, you cannot change the way it works.
But keep your eyes on the ball, the real problem is that the string indeed cannot be found in the dictionary. The reason for that is that your background thread runs with a different culture from your UI thread. Different cultures have different string comparison rules. You either need to give your dictionary a different comparator (StringComparer.InvariantCulture) or you should switch your background thread to the same culture as your UI thread.
Dealing with a non-system default culture in your UI thread can be difficult, all other threads will be started with the system default. Especially threadpool threads are troublesome, you don't always control how they get started. And culture is not part of the Thread.ExecutionContext so doesn't get forwarded. This can cause subtle bugs, like the one you ran into. Other nastiness is, say, SortedList which suddenly becomes unsorted when read by a thread that uses a different culture. Using the system default culture is strongly recommended. Its what your user is likely to use anyway.
The call stack problem is a known issue with Control.Invoke. You lose the call stack. Sorry. This is because it is rethrown on the UI thread using throw ex;.
The best solution would be to replace the background thread with a background Task. Note: this solution is only available for .NET 4.0. The Task class properly marshals exceptions. I wrote a blog entry about reporting progress from tasks, and the code in that blog entry will allow you to catch any UI update errors in the background thread, preserving the original exception and its call stack.
If you can't upgrade to .NET 4.0 yet, there is a workaround. Microsoft's Rx library includes a CoreEx.dll which has an extension method for Exception called PrepareForRethrow. This is supported in .NET 3.5 SP1 and .NET 4.0 (and SL 3 and SL 4). You'll need to wrap your UI updater method with something a little uglier:
private delegate void AddMessageToConsole_DELEGATE (frmMainPresenter.PresenterMessages message);
private void AddMessageToConsole (frmMainPresenter.PresenterMessages message)
{
if (InvokeRequired)
{
// Invoke the target method, capturing the exception.
Exception ex = null;
Invoke((MethodInvoker)() =>
{
try
{
AddMessageToConsole(message);
}
catch (Exception error)
{
ex = error;
}
});
// Handle error if it was thrown
if (ex != null)
{
MSASession.ErrorLogger.Log(ex);
// Rethrow, preserving exception stack
throw ex.PrepareForRethrow();
}
}
else
{
string message_text = ""; //Message that will be displayed in the Console / written in the Log.
try
{
message_text = I18N.GetTranslatedText(message)
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
txtConsole.AppendText(message_text);
}
}
Note: I recommend you start a migration away from ISynchronizeInvoke. It is an outdated interface that is not carried forward into newer UI frameworks (e.g., WPF, Silverlight). The replacement is SynchronizationContext, which supports WinForms, WPF, Silverlight, ASP.NET, etc. SynchronizationContext is much more suitable as an abstract "thread context" for a business layer.
Invoke on a Windows.Forms object causes the function to be invoked on a separate thread. If an Exception is thrown in your invoked function, the Exception is caught and a new TargetInvocationException is thrown.
This TargetInvocationException contains the initial Excpetion in it's InnerException property.
So, try to do it this way:
catch (TargetInvocationException ex) { MSASession.ErrorLogger.Log(ex.InnerException); }
Edit: Also, if you expand the InnerException property in the debugger, you will be able to access it's stacktrace, even if only as plain text.

C# Time of finally execution

Take this code:
using System;
namespace OddThrow
{
class Program
{
static void Main(string[] args)
{
try
{
throw new Exception("Exception!");
}
finally
{
System.Threading.Thread.Sleep(2500);
Console.Error.WriteLine("I'm dying!");
System.Threading.Thread.Sleep(2500);
}
}
}
}
Which gives me this output:
Unhandled Exception: System.Exception: Exception!
at OddThrow.Program.Main(String[] args) in C:\Documents and Settings\username
\My Documents\Visual Studio 2008\Projects\OddThrow\OddThrow\Program.cs:line 14
I'm dying!
My question is: why does the unhandled exception text occur before the finally's? In my mind, the finally should be excuted as the stack unwinds, before we even know that this exception is unhandled. Note the calls to Sleep() - these occur after the unhandled exception is printed, as if it was doing this following:
Unhandled exception text/message
Finally blocks.
Terminate application
According to the C# standard, §8.9.5, this behaviour is wrong:
In the current function member, each try statement that encloses the throw point is examined. For each statement S, starting with the innermost try statement and ending with the outermost try statement, the following steps are evaluated:
If the try block of S encloses the throw point and if S has one or more catch clauses, the catch clauses are examined in order of appearance to locate a suitable handler for the exception. The first catch clause that specifies the exception type or a base type of the exception type is considered a match. A general catch clause (§8.10) is considered a match for any exception type. If a matching catch clause is located, the exception propagation is completed by transferring control to the block of that catch clause.
Otherwise, if the try block or a catch block of S encloses the throw point and if S has a finally block, control is transferred to the finally block. If the finally block throws another exception, processing of the current exception is terminated. Otherwise, when control reaches the end point of the finally block, processing of the current exception is continued.
If an exception handler was not located in the current function member invocation, the function member invocation is terminated. The steps above are then repeated for the caller of the function member with a throw point corresponding to the statement from which the function member was invoked.
If the exception processing terminates all function member invocations in the current thread, indicating that the thread has no handler for the exception, then the thread is itself terminated. The impact of such termination is implementation-defined.
Where am I going wrong? (I've got some custom console error messages, and this is in-the-way. Minor, just annoying, and making me question the language...)
The standard's statements about the order of execution are correct, and not inconsistent with what you are observing. The "Unhandled exception" message is allowed to appear at any point in the process, because it is just a message from the CLR, not actually an exception handler itself. The rules about order of execution only apply to code being executed inside the CLR, not to what the CLR itself does.
What you've actually done is expose an implementation detail, which is that unhandled exceptions are recognised by looking at a stack of which try{} blocks we are inside, rather than by actually exploring all the way to the root. Exceptions may or may not be handled by looking at this stack, but unhandled exceptions are recognised this way.
As you may be aware, if you put a top-level try{}catch{} in your main function, then you will see the behaviour you expect: each function's finally will be executed before checking the next frame up for a matching catch{}.
I could be way off base in the way I'm reading things...but you have a try finally block without a catch.
Juding by the description you posted, since the Exception is never caught, it bubbles up to the caller, works it's way up through the stack, is eventually unhandled, the call terminates, and then the finally block is called.
The output is actually from the default CLR exception handler. Exception Handlers occur before the finally block. After the finally block the CLR terminates because of the unhandled exception (it can't terminate before, as c# guarantees [1] that the finally clause is called).
So I'd say it's just standard behaviour, exception handling occurs before finally.
[1] guranteed during normal operation at least in absence of internal runtime errors or power outage
To add more into the mix, consider this:
using System;
namespace OddThrow
{
class Program
{
static void Main()
{
AppDomain.CurrentDomain.UnhandledException +=
delegate(object sender, UnhandledExceptionEventArgs e)
{
Console.Out.WriteLine("In AppDomain.UnhandledException");
};
try
{
throw new Exception("Exception!");
}
catch
{
Console.Error.WriteLine("In catch");
throw;
}
finally
{
Console.Error.WriteLine("In finally");
}
}
}
}
Which on my system (Norwegian) shows this:
[C:\..] ConsoleApplication5.exe
In catch
In AppDomain.UnhandledException
Ubehandlet unntak: System.Exception: Exception!
ved OddThrow.Program.Main() i ..\Program.cs:linje 24
In finally
Although not completely expected, the program does behave as it should. A finally block is not expected to be run first, it is only expected to be run always.
I adjusted your sample:
public static void Main()
{
try
{
Console.WriteLine("Before throwing");
throw new Exception("Exception!");
}
finally
{
Console.WriteLine("In finally");
Console.ReadLine();
}
}
In this case you will get the nasty unhandled exception dialog, but afterwards the console will output and wait for input, thus executing the finally, just not before windows itself catches the unhandled exception.
A try/finally without a catch will use the default handler which does exactly what you see. I use it all the time, e.g., in cases where handling the exception would be covering an error but there's still some cleanup you want to do.
Also remember that output to standard error and standard out are buffered.
The try-catch-finally blocks are working exactly as you expected if they are caught at some point. When I wrote a test program for this, and I use various nesting levels, the only case that it behaved in a way that matched what you described was when the exception was completely unhandled by code, and it bubbled out to the operating system.
Each time I ran it, the OS was what created the error message.
So the issue is not with C#, it is with the fact that an error that is unhandled by user code is no longer under the control of the application and therefore the runtime (I believe) cannot force an execution pattern on it.
If you had created a windows form application, and wrote all your messages to a textbox (then immediately flushing them) instead of writing directly to the console, you would not have seen that error message at all, because it was inserted into the error console by the calling application and not by your own code.
EDIT
I'll try to highlight the key part of that. Unhandled exceptions are out of your control, and you cannot determine when their exception handler will be executed. If you catch the exception at some point in your application, then the finally blocks will be executed before the lower-in-the-stack catch block.
To put a couple of answers together, what happens is that as soon as you have a Unhandled Exception a UnhandledExceptionEvent is raised on the AppDomain, then the code continues to execute (i.e. the finally). This is the MSDN Article on the event
Next try:
I believe this case isn't mentioned in the c# standard and I agree it seems to almost contradict it.
I believe the internal reason why this is happening is somewhat like this:
The CLR registers its default exception handler as SEH handler into FS:[0]
when you have more catches in your code, those handlers are added to the SEH chain. Alternatively, only the CLR handler is called during SEH handling and handles the CLR exception chain internally, I don't know which.
In your code when the exception is thrown, only the default handler is in the SEH chain. This handler is called before any stack unrolling begins.
The default exception handler knows that there are no exception handler registered on the stack. Therefore it calls all registered UnhandledException handler first, then prints its error message and marks the AppDomain for unloading.
Only after that stack unrolling even begins and finally blocks are called according the c# standard.
As i see it, the way the CLR handles unhandled exception isn't considered in the c# standard, only the order in which finallys are called during stack unrolling. This order is preserved. After that the "The impact of such termination is implementation-defined." clause takes effect.

Categories