I'm using .NET 1.1 compability mode for unhandled exception handling. The problem is that when LegacyUnhandledExceptionPolicy is set to "1" (which is what I want), I cannot catch and swallow ThreadAbortException.
Example code:
App.config:
<configuration>
<runtime>
<legacyUnhandledExceptionPolicy enabled="1"/>
</runtime>
</configuration>
Code:
class Program {
static void Main(string[] args) {
AppDomain.CurrentDomain.UnhandledException += _onBackgroundThreadCrash;
var t = new Thread(_worker) { IsBackground = true };
t.Start();
Thread.Sleep(1000);
t.Abort();
Console.ReadLine();
}
private static void _worker() {
try {
while (true);
} catch (ThreadAbortException) {
// expected thread exit, don't rethrow
}
}
private static void _onBackgroundThreadCrash(object sender, UnhandledExceptionEventArgs e) {
Console.WriteLine(e.ExceptionObject as Exception);
}
}
When legacy exceptions handling is "0" (OFF), the above code swallows ThreadAbortException queitly, as expected.
But, when legacy exceptions handling is "1" the above code prints ThreadAbortException to console, which is not what I expect.
Any ideas?
Thanks.
You cannot catch a ThreadAbortException, it is always re-raised after catching it. There are two basic solutions to your problem.
First one is that you reset the abort request:
catch (ThreadAbortException) {
// expected thread abort request, reset it and exit thread
Thread.ResetAbort();
}
Second one is to address the other thing that happens when you enable legacy exception handling. The AppDomain.UnhandledException event is now also raised for non-fatal exceptions. Write your exception handler like this:
private static void _onBackgroundThreadCrash(object sender, UnhandledExceptionEventArgs e) {
if (e.IsTerminating) {
Console.WriteLine(e.ExceptionObject as Exception);
}
}
I'd have to recommend the first solution, you really don't want unhandled exceptions that terminate a thread to leave no trace at all.