In a c# threading app, if I were to lock an object, let us say a queue, and if an exception occurs, will the object stay locked? Here is the pseudo-code:
int ii;
lock(MyQueue)
{
MyClass LclClass = (MyClass)MyQueue.Dequeue();
try
{
ii = int.parse(LclClass.SomeString);
}
catch
{
MessageBox.Show("Error parsing string");
}
}
As I understand it, code after the catch doesn't execute - but I have been wondering if the lock will be freed.
I note that no one has mentioned in their answers to this old question that releasing a lock upon an exception is an incredibly dangerous thing to do. Yes, lock statements in C# have "finally" semantics; when control exits the lock normally or abnormally, the lock is released. You're all talking about this like it is a good thing, but it is a bad thing! The right thing to do if you have a locked region that throws an unhandled exception is to terminate the diseased process immediately before it destroys more user data, not free the lock and keep on going.
Look at it this way: suppose you have a bathroom with a lock on the door and a line of people waiting outside. A bomb in the bathroom goes off, killing the person in there. Your question is "in that situation will the lock be automatically unlocked so the next person can get into the bathroom?" Yes, it will. That is not a good thing. A bomb just went off in there and killed someone! The plumbing is probably destroyed, the house is no longer structurally sound, and there might be another bomb in there. The right thing to do is get everyone out as quickly as possible and demolish the entire house.
I mean, think it through: if you locked a region of code in order to read from a data structure without it being mutated on another thread, and something in that data structure threw an exception, odds are good that it is because the data structure is corrupt. User data is now messed up; you don't want to try to save user data at this point because you are then saving corrupt data. Just terminate the process.
If you locked a region of code in order to perform a mutation without another thread reading the state at the same time, and the mutation throws, then if the data was not corrupt before, it sure is now. Which is exactly the scenario that the lock is supposed to protect against. Now code that is waiting to read that state will immediately be given access to corrupt state, and probably itself crash. Again, the right thing to do is to terminate the process.
No matter how you slice it, an exception inside a lock is bad news. The right question to ask is not "will my lock be cleaned up in the event of an exception?" The right question to ask is "how do I ensure that there is never an exception inside a lock? And if there is, then how do I structure my program so that mutations are rolled back to previous good states?"
First; have you considered TryParse?
in li;
if(int.TryParse(LclClass.SomeString, out li)) {
// li is now assigned
} else {
// input string is dodgy
}
The lock will be released for 2 reasons; first, lock is essentially:
Monitor.Enter(lockObj);
try {
// ...
} finally {
Monitor.Exit(lockObj);
}
Second; you catch and don't re-throw the inner exception, so the lock never actually sees an exception. Of course, you are holding the lock for the duration of a MessageBox, which might be a problem.
So it will be released in all but the most fatal catastrophic unrecoverable exceptions.
yes, that will release properly; lock acts as try/finally, with the Monitor.Exit(myLock) in the finally, so no matter how you exit it will be released. As a side-note, catch(... e) {throw e;} is best avoided, as that damages the stack-trace on e; it is better not to catch it at all, or alternatively: use throw; rather than throw e; which does a re-throw.
If you really want to know, a lock in C#4 / .NET 4 is:
{
bool haveLock = false;
try {
Monitor.Enter(myLock, ref haveLock);
} finally {
if(haveLock) Monitor.Exit(myLock);
}
}
"A lock statement is compiled to a call to Monitor.Enter, and then a try…finally block. In the finally block, Monitor.Exit is called.
The JIT code generation for both x86 and x64 ensures that a thread abort cannot occur between a Monitor.Enter call and a try block that immediately follows it."
Taken from:
This site
Just to add a little to Marc's excellent answer.
Situations like this are the very reason for the existence of the lock keyword. It helps developers make sure the lock is released in the finally block.
If you're forced to use Monitor.Enter/Exit e.g. to support a timeout, you must make sure to place the call to Monitor.Exit in the finally block to ensure proper release of the lock in case of an exception.
Your lock will be released properly. A lock acts like this:
try {
Monitor.Enter(myLock);
// ...
} finally {
Monitor.Exit(myLock);
}
And finally blocks are guaranteed to execute, no matter how you leave the try block.
Related
Today I've run into this:
https://blogs.msdn.microsoft.com/ericlippert/2009/03/06/locks-and-exceptions-do-not-mix/
I am using .net 2.0, so, basically, this code
lock(syncRootVar) {
DoStuff();
}
Will unfold into this
Monitor.Enter(syncRootVar);
try {
DoStuff();
} finally {
Monitor.Exit(syncRootVar);
}
As Lippert wrote on the blog, there might be a nop operation between the Enter call and the try-finally block, being a potential position for a thread abort exception to be raised and therefore messing up with the lock.
I have two questions about this:
Is there a common way of handling this troublesome situation and still clean up the lock object in order to not affect other threads?
Are there other situations that might result in the lock being acquired, but exceptions raising before the try-finally block?
As the article points out, the issue you seem to be concerned with is no longer an issue. The C# compiler has been changed (and presumably with Roslyn will retain the change) so that the lock is taken inside the try/finally. It's not possible to take the lock but fail to execute the finally clause.
Now (also as the article points out) you have a different problem: if the code in the protected block of code is mutating state, an exception could result in other code seeing partially-mutated state. This may or may not be a problem; usually it would be, but of course each specific scenario is different. It's possible some code would be safe in such a case.
• Is there a common way of handling this troublesome situation and still clean up the lock object in order to not affect other threads?
For the specific situation you've asked about, the two biggest things you can do are:
Don't abort threads. This is always good advice and should always be followed. If you don't abort a thread, you won't have that problem.
Use the latest version of the compiler. The newer versions of the compiler don't generate code that would be susceptible to the problem.
• Are there other situations that might result in the lock being acquired, but exceptions raising before the try-finally block?
No, not with the latest version of the compiler. There's not even the original situation.
Now what about that pesky "partially-mutated" issue? Well, you'll have to address each case individually. But if an exception might be thrown, and leaving the lock with partially-mutated state is possible, then you'll have to add your own clean-up code. E.g.:
lock(syncRootVar) {
try {
DoStuff();
} catch {
UndoStuff();
throw;
}
}
I have the following code:
using (Mutex mut = new Mutex(false, MUTEX_NAME))
{
if (mut.WaitOne(new TimeSpan(0, 0, 30)))
{
// Some code that deals with a specific TCP port
// Don't want this to run at the same time in another process
}
}
I've set a breakpoint within the if block, and ran the same code within another instance of Visual Studio. As expected, the .WaitOne call blocks. However, to my surprise, as soon as I continue in the first instance and the using block terminates, I get an exception in the second process about an abandoned Mutex.
The fix is to call ReleaseMutex:
using (Mutex mut = new Mutex(false, MUTEX_NAME))
{
if (mut.WaitOne(new TimeSpan(0, 0, 30)))
{
// Some code that deals with a specific TCP port
// Don't want this to run twice in multiple processes
}
mut.ReleaseMutex();
}
Now, things work as expected.
My Question: Usually the point of an IDisposable is it cleans up whatever state you put things in. I could see perhaps having multiple waits and releases within a using block, but when the handle to the Mutex is disposed, shouldn't it get released automatically? In other words, why do I need to call ReleaseMutex if I'm in a using block?
I'm also now concerned that if the code within the if block crashes, I'll have abandoned mutexes lying around.
Is there any benefit to putting Mutex in a using block? Or, should I just new up a Mutex instance, wrap it in a try/catch, and call ReleaseMutex() within the finally block (Basically implementing exactly what I thought Dispose() would do)
The documentation explains (in the "Remarks" section) that there is a conceptual difference between instantiating a Mutex object (which does not, in fact, do anything special as far as synchronization goes) and acquiring a Mutex (using WaitOne). Note that:
WaitOne returns a boolean, meaning that acquiring a Mutex can fail (timeout) and both cases must be handled
When WaitOne returns true, then the calling thread has acquired the Mutex and must call ReleaseMutex, or else the Mutex will become abandoned
When it returns false, then the calling thread must not call ReleaseMutex
So, there's more to Mutexes than instantiation. As for whether you should use using anyway, let's take a look at what Dispose does (as inherited from WaitHandle):
protected virtual void Dispose(bool explicitDisposing)
{
if (this.safeWaitHandle != null)
{
this.safeWaitHandle.Close();
}
}
As we can see, the Mutex is not released, but there is some cleanup involved, so sticking with using would be a good approach.
As to how you should proceed, you can of course use a try/finally block to make sure that, if the Mutex is acquired, that it gets properly released. This is likely the most straightforward approach.
If you really don't care about the case where the Mutex fails to be acquired (which you haven't indicated, since you pass a TimeSpan to WaitOne), you could wrap Mutex in your own class that implements IDisposable, acquire the Mutex in the constructor (using WaitOne() with no arguments), and release it inside Dispose. Although, I probably wouldn't recommend this, as this would cause your threads to wait indefinitely if something goes wrong, and regardless there are good reasons for explicitly handling both cases when attempting an acquire, as mentioned by #HansPassant.
This design decision was made a long, long time ago. Over 21 years ago, well before .NET was ever envisioned or the semantics of IDisposable were ever considered. The .NET Mutex class is a wrapper class for the underlying operating system support for mutexes. The constructor pinvokes CreateMutex, the WaitOne() method pinvokes WaitForSingleObject().
Note the WAIT_ABANDONED return value of WaitForSingleObject(), that's the one that generates the exception.
The Windows designers put the rock-hard rule in place that a thread that owns the mutex must call ReleaseMutex() before it exits. And if it doesn't that this is a very strong indication that the thread terminated in an unexpected way, typically through an exception. Which implies that synchronization is lost, a very serious threading bug. Compare to Thread.Abort(), a very dangerous way to terminate a thread in .NET for the same reason.
The .NET designers did not in any way alter this behavior. Not in the least because there isn't any way to test the state of the mutex other than by performing a wait. You must call ReleaseMutex(). And do note that your second snippet is not correct either; you cannot call it on a mutex that you didn't acquire. It must be moved inside of the if() statement body.
Ok, posting an answer to my own question. From what I can tell, this is the ideal way to implement a Mutex that:
Always gets Disposed
Gets Released iff WaitOne was successful.
Will not get abandoned if any code throws an exception.
Hopefully this helps someone out!
using (Mutex mut = new Mutex(false, MUTEX_NAME))
{
if (mut.WaitOne(new TimeSpan(0, 0, 30)))
{
try
{
// Some code that deals with a specific TCP port
// Don't want this to run twice in multiple processes
}
catch(Exception)
{
// Handle exceptions and clean up state
}
finally
{
mut.ReleaseMutex();
}
}
}
Update: Some may argue that if the code within the try block puts your resource in an unstable state, you should not release the Mutex and instead let it get abandoned. In other words, just call mut.ReleaseMutex(); when the code finishes successfully, and not put it within the finally block. The code acquiring the Mutex could then catch this exception and do the right thing.
In my situation, I'm not really changing any state. I'm temporarily using a TCP port and can't have another instance of the program run at the same time. For this reason, I think my solution above is fine but yours may be different.
One of the primary uses of a mutex is to ensure that the only code which will ever see a shared object in a state which doesn't satisfy its invariants is the code which (hopefully temporarily) put the object into that state. A normal pattern for code which needs to modify an object is:
Acquire mutex
Make changes to object which cause its state to become invalid
Make changes to object which cause its state to become valid again
Release mutex
If something goes wrong in after #2 has begun and before #3 has finished, the object may be left in a state which does not satisfy its invariants. Since the proper pattern is to release a mutex before disposing it, the fact that code disposes a mutex without releasing it implies that something went wrong somewhere. As such, it may not be safe for code to enter the mutex (since it hasn't been released), but there's no reason to wait for the mutex to be released (since--having been disposed--it never will be). Thus, the proper course of action is to throw an exception.
A pattern which is somewhat nicer than the one implemented by the .NET mutex object is to have the "acquire" method return an IDisposable object which encapsulates not the mutex, but rather a particular acquisition thereof. Disposing that object will then release the mutex. Code can then look something like:
using(acq = myMutex.Acquire())
{
... stuff that examines but doesn't modify the guarded resource
acq.EnterDanger();
... actions which might invalidate the guarded resource
... actions which make it valid again
acq.LeaveDanger();
... possibly more stuff that examines but doesn't modify the resource
}
If the inner code fails between EnterDanger and LeaveDanger, then the acquisition object should invalidate the mutex by calling Dispose on it, since the guarded resource may be in a corrupted state. If the inner code fails elsewhere, the mutex should be released since the guarded resource is in a valid state, and the code within the using block won't need to access it anymore. I don't have any particular recommendations of libraries implementing that pattern, but it isn't particularly difficult to implement as a wrapper around other kinds of mutex.
We need to understand more then .net to know what is going on the start of the MSDN page gives the first hint that someone “odd” is going on:
A synchronization primitive that can also be used for interprocess
synchronization.
A Mutex is a Win32 “Named Object”, each process locks it by name, the .net object is just a wrapper round the Win32 calls. The Muxtex itself lives within the Windows Kernal address space, not your application address space.
In most cases you are better off using a Monitor, if you are only trying to synchronizes access to objects within a single process.
If you need to garantee that the mutex is released switch to a try catch finally block and put the mutex release in the finally block. It is assumed that you own and have a handle for the mutex. That logic needs to be included before release is invoked.
Reading the documentation for ReleaseMutex, it seems the design decision was that a Mutex should be released consciously. if ReleaseMutex isn't called, it signifies an abnormal exit of the protected section. putting the release in a finally or dispose, circumvents this mechanism. you are still free to ignore the AbandonedMutexException, of course.
Be aware: The Mutex.Dispose() executed by the Garbage collector fails because the garbage collection process does not own the handle according Windows.
Dispose depends on WaitHandle to be released. So, even though using calls Dispose, it won't go into affect until the the conditions of stable state are met. When you call ReleaseMutex you're telling the system that you're releasing the resource, and thus, it is free to dispose of it.
For the last question.
Is there any benefit to putting Mutex in a using block? Or, should I just new up a Mutex instance, wrap it in a try/catch, and call ReleaseMutex() within the finally block (Basically implementing exactly what I thought Dispose() would do)
If you don't dispose of the mutex object, creating too many mutex objects may encounter the following issue.
---> (Inner Exception #4) System.IO.IOException: Not enough storage is available to process this command. : 'ABCDEFGHIJK'
at System.Threading.Mutex.CreateMutexCore(Boolean initiallyOwned, String name, Boolean& createdNew)
at NormalizationService.Controllers.PhysicalChunkingController.Store(Chunk chunk, Stream bytes) in /usr/local/...
The program uses the named mutex and runs 200,000 times in the parallel for loop. Adding using statement resolves the issue.
Can Monitor.Enter throw any exception. I am doing a code review and find that Monitor.Enter is before try block. Do you see any issues with in?
Monitor.Enter(...)
try
{
...
}
finally
{
Monitor.Exit(..)
}
This is the correct pattern, whether Enter() throws (can throw) or not.
Only after the call to Enter() succeeds your code is under the responsibility to call Exit().
Suppose the call to Enter() fails. Then calling the corresponding Exit() is simply incorrect, it will make matters worse. So Enter() has to be outside (before) the try block.
Hans Passant's comment is of course correct. If Monitor.Enter throws before the lock is taken then you do not want the finally to run. If it throws after the lock is taken and after the try is entered, then the lock is released. (More on this later.) But if the throw happens after the lock is taken but before the try is entered, then the lock will never be cleaned up.
This is a rare but possible situation.
In C# 4 we changed the codegen of the lock statement so that the monitor enter is inside the try. This ensures that the lock is always released if something throws after the lock is taken. However, note that this might still be wrong. If something throws after the lock is taken then whatever non-atomic mutation the lock is protecting might be half-completed, and the finally block then unlocks the lock and allows access to the inconsistent state! The fundamental problem here is that you shouldn't be throwing inside a lock in the first place.
See my article about the issue for more discussion.
Monitor.Enter can throw at least the following exceptions
ArgumentNullException of the parameter is null
ThreadInterruptedException if the thread doing the Enter has it's Interrupt method invoked.
If it acquires the lock, then no.
But an exception might be thrown between the Monitor.Enter and the try block.
The recommended method is the new Enter method, new in .NET 4:
public static void Enter( obj, ref bool lockTaken )
Is there anything wrong with using lock with a try block? I remember reading somewhere that we should always try to put minimum amount of code within try block and lock itself internally uses a try-finally block, do you guys see something wrong here.I need to deal with the fact that the code within that lock block can throw exception
try
{
lock(syncblk)
{
// do some processing
}
}
catch(Exception e)
{
// do something with exception
}
I need to deal with the fact that the code within that lock block can throw exception
And there's your problem. That's a terrible situation to be in.
Why are you locking in the first place? Usually the reason why you lock something is because you want to implement the following logic:
lock the door
make a mess
clean it up
unlock the door
If you do that, then no one who honours the locked door ever sees the mess.
For example, you might want to swap values of variables "left" and "right" in a threadsafe manner, so you:
take the lock
read the left variable into tempLeft
read the right variable into tempRight
write tempLeft into right
we just made a mess; the original value of 'right' has gone missing
write tempRight into left
we've cleaned up the mess, all is well with the world again
release the lock
Now suppose an exception is thrown after the mess is made. What happens? We jump straight to the unlock, leaving the mess for another thread to see.
That's why you should never throw an exception inside a lock; it completely defeats the purpose of the lock! The whole point of a lock is to ensure that state is always observed to be consistent by all threads except the one responsible for cleaning up the mess.
If you have an exception that can be thrown from inside a lock, the best thing to do is to get out of that horrible situation. If you can't do that, then make sure that you can either (1) destroy the process utterly as soon as the exception escapes the lock, so that the mess you made cannot cause data loss or other harm -- do a FailFast and nuke the process from orbit, it's the only way to be sure -- or (2) write rollback code that undoes whatever operation you were attempting before the lock is exited; that is, clean up the mess back to the original state.
If the latter is your strategy then don't put the try block outside the lock; it's useless there because the instant control leaves the lock via the exception another thread can be crashing and dying because of the mess you left exposed to it. Put the try that deals with the exception inside the lock:
lock(whatever)
{
try
{
MakeAMess();
}
finally
{
CleanItUp();
// Either by completing the operation or rolling it back
// to the pre-mess state
}
}
If you have strong reliability requirements then dealing with locked critical sections which can throw exceptions is an extremely difficult programming task best left to experts; you might consider using a constrained execution region if you find yourself in this situation a lot.
I think you can do it your way but here is the MSDN description on lock for your information. Please refer to http://msdn.microsoft.com/en-us/library/ms173179.aspx for more info.
Using the lock (C#) or SyncLock
(Visual Basic) keyword is generally
preferred over using the Monitor class
directly, both because lock or
SyncLock is more concise, and because
lock or SyncLock insures that the
underlying monitor is released, even
if the protected code throws an
exception. This is accomplished with
the finally keyword, which executes
its associated code block regardless
of whether an exception is thrown.
So I am not sure what kind of exception you are referring to but if you concern is that you may not be able to release the lock because of exception, you do not have to worry about it.
you can always use the longer syntax like this:
System.Threading.Monitor.Enter(x);
try {
...
}
catch(Exception e)
{
}
finally {
System.Threading.Monitor.Exit(x);
}
I've just finished reading "C# 4.0 in a Nutshell" (O'Reilly) and I think it's a great book for a programmer willing to switch to C#, but it left me wondering. My problem is the definition of using statement. According to the book (p. 138),
using (StreamReader reader = File.OpenText("file.txt")) {
...
}
is precisely equivalent to:
StreamReader reader = File.OpenText("file.txt");
try {
...
} finally {
if (reader != null)
((IDisposable)reader).Dispose();
}
Suppose, however, that this is true and that this code is executed in a separate thread. This thread is now aborted with thread.Abort(), so a ThreadAbortException is thrown and suppose the thread is exactly after initializing the reader and before entering the try..finally clause. This would mean that the reader is not disposed!
A possible solution would be to code this way:
StreamReader reader = null;
try {
reader = File.OpenText("file.txt");
...
} finally {
if (reader != null)
((IDisposable)reader).Dispose();
}
This would be abort-safe.
Now for my questions:
Are authors of the book right and the using statement is not abort-safe or are they wrong and it behaves like in my second solution?
If using is equivalent to the first variant (not abort-safe), why does it check for null in finally?
According to the book (p. 856), ThreadAbortException can be thrown anywhere in managed code. But maybe there are exceptions and the first variant is abort-safe after all?
EDIT: I know that using thread.Abort() is not considered good practice. My interest is purely theoretical: how does the using statement behave exactly?
The book's companion web site has more info on aborting threads here.
In short, the first translation is correct (you can tell by looking at the IL).
The answer to your second question is that there may be scenarios where the variable can be legitimately null. For instance, GetFoo() may return null here, in which you wouldn't want a NullReferenceException thrown in the implicit finally block:
using (var x = GetFoo())
{
...
}
To answer your third question, the only way to make Abort safe (if you're calling Framework code) is to tear down the AppDomain afterward. This is actually a practical solution in many cases (it's exactly what LINQPad does whenever you cancel a running query).
There's really no difference between your two scenarios -- in the second, the ThreadAbort could still happen after the call to OpenText, but before the result is assigned to the reader.
Basically, all bets are off when you get a ThreadAbortException. That's why you should never purposely abort threads rather than using some other method of gracefully bringing the thread to a close.
In response to your edit -- I would point out again that your two scenarios are actually identical. The 'reader' variable will be null unless the File.OpenText call successfully completes and returns a value, so there's no difference between writing the code out the first way vs. the second.
Thread.Abort is very very bad juju; if people are calling that you're already in a lot of trouble (unrecoverable locks, etc). Thread.Abort should really be limited to the scanerio of inhuming a sickly process.
Exceptions are generally unrolled cleanly, but in extreme cases there is no guarantee that every bit of code can execute. A more pressing example is "what happens if the power fails?".
Re the null check; what if File.OpenText returned null? OK, it won't but the compiler doesn't know that.
A bit offtopic but the behaviour of the lock statement during thread abortion is interesting too. While lock is equivalent to:
object obj = x;
System.Threading.Monitor.Enter(obj);
try {
…
}
finally {
System.Threading.Monitor.Exit(obj);
}
It is guaranteed(by the x86 JITter) that the thread abort doesn't occur between Monitor.Enter and the try statement.
http://blogs.msdn.com/b/ericlippert/archive/2007/08/17/subtleties-of-c-il-codegen.aspx
The generated IL code seems to be different in .net 4:
http://blogs.msdn.com/b/ericlippert/archive/2009/03/06/locks-and-exceptions-do-not-mix.aspx
The language spec clearly states that the first one is correct.
http://msdn.microsoft.com/en-us/vcsharp/aa336809.aspx MS Spec(Word document)
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf ECMA Spec
In case of a thread aborting both code variants can fail. The second one if the abort occurs after the expression has been evaluated but before the assignment to the local variable occurred.
But you shouldn't use thread abortion anyways since it can easily corrupt the state of the appdomain. So only abort threads if you force unload an appdomain.
You are focusing on the wrong problem. The ThreadAbortException is just as likely to abort the OpenText() method. You might hope that it is resilient to that but it isn't. The framework methods do not have try/catch clauses that try to deal with a thread abort.
Do note that the file doesn't remain opened forever. The FileStream finalizer will, eventually, close the file handle. This of course can still cause exceptions in your program when you keep running and try to open the file again before the finalizer runs. Albeit that this is something you always have to be defensive about when you run on a multi-tasking operating system.
Are authors of the book right and the using statement is not abort-safe or are they wrong and it behaves like in my second solution?
According to the book (p. 856), ThreadAbortException can be thrown anywhere in managed code. But maybe there are exceptions and the first variant is abort-safe after all?
The authors are right. The using block is not abort-safe. Your second solution is also not abort-safe, the thread could be aborted in the middle of the resource acquisition.
Although it's not abort-safe, any disposable that has unmanged resources should also implement a finalizer, which will eventually run and clean up the resource. The finalizer should be robust enough to also take care of not completely initialized objects, in case the thread aborts in the middle of the resource acquisition.
A Thread.Abort will only wait for code running inside Constrained Execution Regions (CERs), finally blocks, catch blocks, static constructors, and unmanaged code. So this is an abort-safe solution (only regarding the acquisition and disposal of the resource):
StreamReader reader = null;
try {
try { }
finally { reader = File.OpenText("file.txt"); }
// ...
}
finally {
if (reader != null) reader.Dispose();
}
But be careful, abort-safe code should run fast and not block. It could hang a whole app domain unload operation.
If using is equivalent to the first variant (not abort-safe), why does it check for null in finally?
Checking for null makes the using pattern safe in the presence of null references.
The former is indeed exactly equivalent to the latter.
As already pointed out, ThreadAbort is indeed a bad thing, but it's not quite the same as killing the task with Task Manager or switching off your PC.
ThreadAbort is an managed exception, which the runtime will raise when it is possible, and only then.
That said, once you're into ThreadAbort, why bother trying to cleanup? You're in death throes anyway.
the finally-statement is always executed, MSDN says "finally is used to guarantee a statement block of code executes regardless of how the preceding try block is exited."
So you don't have to worry about not cleaning resources etc (only if windows, the Framework-Runtime or anything else bad you can't control happens, but then there are bigger problems than cleaning up Resources ;-))