Writing multithreaded code is hard. It will never be easy.
Every few years, someone comes up with a "genius" idea that will magically fix all multithreading and synchronizing problems so that programmers will never have to bother with them again. Every single time, the idea fails. Whenever I feel narcissistic enough to be contemplating an automatic synchronization framework, I just tell myself: "Smarter people than you have spent decades on this without finding a solution."
Two.NET examples spring to mind:
1) MethodImplOptions.Synchronized. The docs have been revised to state "... the Synchronized flag is not recommended for public types... This might cause deadlocks or other synchronization problems." The very first Google hit on "MethodImplOptions.Synchronized" is an MSDN blog containing the illuminating text "this is one of those ones that goes into the “don't do that�bucket".
2) The collection auto-synchronization scheme (ICollection.SyncRoot, ICollection.IsSynchronized, *.Synchronized()). The docs now state "Enumerating through a collection is intrinsically not a thread-safe procedure. Even when a collection is synchronized, other threads can still modify the collection..." Note that the 2.0 generic collections abandoned this whole system, not supporting the Synchronized method andalways returning false for IsSynchronized.
Now, that's not to say that multithreading won't always be as hard as it is now. There's a lot of promising work being done in purely functional systems, where everything is immutable (and thus intrinsically threadsafe) once it has been created. PLINQ is fascinating. I've written
Nito.Async to help programmers with multithreading/synchronization issues, but it's still hard.
Back to the original question: as Hans said, your code has a bug. It is not aflaw in the framework.The case cannot "be handled safely" automatically. If you're interested in advanced deadlock detection, check out this MSDN article:
Avoiding and Detecting .NET Deadlocks. It only covers the "lock" case, but it can be extended to include events, mutexes, etc. with a considerable amount of work. ;)
But that's just detection.Then there's the classic problem that there is no such thing as a "correct recovery" from a deadlock. :)
I'm going to go now. My mind has been bent enough already this morning. :)
-Steve
Programming blog:
http://nitoprograms.blogspot.com/
Including my
TCP/IP .NET Sockets FAQ
MSBuild user? Try out the DynamicExecute task in the
MSBuild Extension Pack source; it's currently in Beta so get your comments in!