Here's a puzzle for you guys. I have a multithreaded program in which some threads work with managed resources like locks and semaphores. Some of the lock release primitives can only be performed from the same thread on which the lock acquire was done.
So here's my puzzle: I wrap these kinds of operations: try { lock-acquire... do something } finally { lock-release }, but sometimes when my threads terminate, the finally clauses are performed by the .NET garbage collection thread and not by my thread. (The specific case actually involves the Dispose of an object allocated in a "using" statement; see below for details)
This is a little tricky to demo; I see it all the time in Isis2, and I've figured out that this is happening by checking the thread-ids in the acquire and finalize blocks. But I don't have a 3-line demo for you, and I am sorry about that. I know it would make it easier to provide help.
Is there a way I can delay termination for a thread until all pending finalize blocks associated with that thread have executed?
---- Details added for Mark ----
What I'm really doing involves a fairly elaborate self-instrumenting locking package that has various locking abstractions (bounded buffers, barriers, normal locks, etc) with thread priorities and designed to self-detect deadlocks, priority inversions, very slow lock grants and other problems. My code is complex enough and threaded enough so that I needed this to debug it.
An example of my basic style of construct is this:
LockObject myLock = new LockObject("AnIsis2Lock");
...
using(new LockAndElevate(myLock)) { stuff }
A LockObject is a self-monitoring lock... a LockAndElevate makes note that I locked it (in this case) and later tracks the dispose, when I unlock it. So I'm exploiting the fact that using should dispose of the new object when the block completes -- even if it throws an exception.
What I'm seeing is that fairly often, threads terminate and yet the using dispose events haven't actually occurred; they run later, on some other thread. This only happens when one of my threads terminates; in normal execution, the whole thing works like a charm.
So since using translates to try... finally, my question was posted in terms of finally clauses.