Reputation: 5523
According to MSDN, AppDomain.Unload causes all threads inside the unloading AppDomain to throw a thread abort exception.
The threads in domain are terminated using the Abort method, which throws a ThreadAbortException in the thread. Although the thread should terminate promptly, it can continue executing for an unpredictable amount of time in a finally clause. -- from MSDN
So my understanding then is that everytime i'm writing code anywhere that is expected to run in this AppDomain, I have to expect that a thread abort could happen on any thread at any time. Is this true? Should all code everywhere assume that a ThreadAbortException can be thrown at any time?
Practically this virtually elimates catch(Exception ex) because that would catch the ThreadAbortException and try to handle it, usually by logging an error that really shouldn't be logged (since unloading of AppDomain isn't really an exception).
Are there any other considerations that need to be taken to avoid unecessary exception handling / error logging?
Upvotes: 2
Views: 2400
Reputation: 51344
You pretty much have the expectation correct regarding the possibility of TAEs at any time. The only point I'd make is that your code should probably already be written this way- when handling data that has reliability requirements, you should be using transactions or other compensation mechanisms in cases of hardware failure, operator error, OOMs, etc - any of which are not unique to the scenario of AppDomain shutdown.
Finally, you should know that you can catch TAEs and execute compensatory code in the catch block. The only thing special about them is that they will be immediately rethrown after the catch block, so you can't "swallow" them. You can suppress them by using Thread.ResetAbort()
, but in this case that probably isn't the desired effect.
We've all written code like this:
public void Foo() {
try {
Do.Some.Stuff();
} catch (Exception ex) {
Console.Out.WriteLine("Oh noes!");
}
}
And yes, the catch block will catch everything1, including TAEs and OOMs.
The thing to keep in mind here is that for all of the above exceptions, the world is basically ending. All you should care about is that whatever transactionally sensitive data that you are dealing with doesn't get lost or left in a bad state, and that's why we generally leave things like transactionally-safe I/O to the smart folks at Microsoft and Oracle who write databases. If your code is doing, for instance, flat file I/O that you need to be really sure never leaves the file in a bad state, then you should be thinking about failure modes in a very holistic way- like "what happens if the power goes out when this file is half-written?"
1 The sole exception is that StackOverflow exceptions generally cannot be caught. This was a change in .NET 2.0.
Upvotes: 5