Hmmm, I couldn’t really think of a good title except that this blog post has a little bit of everything of the title. As with any multithreaded program, deadlocks are a huge pain in the butt, and when they happen it costs time, money, and stress. In my code base I’ve introduced something called an ExtendedLock, which basically has something like this inside: 1: public class ExtendedLock : IExtendedLock { 2: public IDisposable Lock() { 3: while (!Monitor.TryEnter(this, 5000)) { 4: IncrementLockTime(); 5: } 6: return new Disposer(() => Release()); 7: } 8: public event Deadlock;9: } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Pretty simple. IncrementLockTime, as the name implies keeps track of how long the current thread has been attempting to acquire the lock. It returns a Disposer which takes an Action, which releases the lock. This allows us to take advantage of the using syntax, and avoid boiler plate try/finally (oh, and it avoids typos in Monitor.Exit). After some configurable amount of time, if the lock cannot be acquired within, say, 2 minutes, it’s probably a good probability your application is blocked somewhere.
Read on...