Sample code: LockHelper.cs [6KB]

Debugging threading issues is painful.

Really painful.

One of the most painful problems: dealing with deadlocks--waiting forever on a Monitor.Enter (C# lock) and not knowing which thread already has the lock.

I tried to dig in on this on the CLR Base Class Library Forum. I was hopeful, since Java has a method [Thread.holdsLock(obj)] that returns the holder of the current lock

Sadly, .NET lacks this functionality.

Enter a can-do attitude: why not build it myself.

Enter LockHelper.

Goals:

  • Identical semantics to Monitor.Enter/Exit
  • Enable other Monitor features (Pulse, Wait)
  • Close to identical syntax to C# lock
  • Ability to know, given an instance of LockHelper, the current owning thread
  • Other conveniences (CheckAccess and VerifyAccess)

Wrapping Monitor.Enter/Exit isn't that hard. As you see with the implementation, it's pretty easy to leverage IDisposable + the C# using statement to get syntax that is close to lock.

Instead of:

public void Foo()
{
    lock(m_lockObject)
    {
        //do stuff
    }
}

private readonly object m_lockObject = new object();

Do this:

public void Foo()
{
    using(m_lockObject.GetLock())
    {
        //do stuff
    }
}

private readonly LockHelper m_lockObject = new LockHelper("foo");

GetLock() returns a private class that implements IDisposable. The using block has identical try/finally semantics to the lock keyword. (See this article in the C# Programming Guide for details.)

I had to be religious about storing away Thread.Name for the current thread at all times. While debugging, I found that VS was often unable to evaluate the property of the owning thread.

So now I have enough plumbing to figure out which thread has a lock on my lock object. Cool.

What else?

Exposing Pulse and Wait was pretty easy. Beyond these basics, I stole the CheckAccess/VerifyAccess ideas from WPF.

Often times one will have private helpers in a class that access/modify the state of a class. Often times these methods (should) run under the assumption that they were called in the context of a lock.

The simple way around this is to re-lock the object inside the helper method, but this can be a source of deadlocks and really doesn't help maintain the implementation contract.

What one wants: a way to assert that the calling thread owns a lock.

Done!

CheckAccess returns true if the current thread has the lock. Otherwise, false.

VerifyAccess goes a step further and throws an exception if the calling thread doesn't own the lock.

Pretty cool, huh?

Note: I was not on the CLR team at Microsoft. I was not a developer at Microsoft, just a lowly PM. I'm pretty confident this works. At least I haven't hit any issues with it. Please be careful throwing this in your own projects. This is certainly out of the realm of advertised best-practices from MS.

It works for me, though.

Let me know what you think.

Happy hacking!