The question is, can I create a class that gets notified when it is locked and unlocked.
object myLockObj = new SpecialLockNotifyClass("Bob");
lock (myLockObj)
{
Console.WriteLine("Hello");
}
And the output you would get is:
Trying to lock Bob.
Bob is locked.
Hello.
Bob is unlocked.
The idea is two-fold:
1) Set it up so one can see when something is trying to lock (by seeing "trying" message" and waiting indefinitely (by not seeing "locked" message) everywhere the lock is used
2) Turn off the outputs and switch back to standard locking when one believes the deadlock problems are solved.
lock
is just syntactic sugar for Monitor.Enter/Monitor.Exit.
You could wrap the Monitor access in a custom Disposable type, and replace your lock
block with a using
block. EG
sealed class MyLock : IDisposable
{
private object syncRoot;
bool lockWasTaken = false;
public MyLock(object syncRoot)
{
this.syncRoot = syncRoot;
BeforeLock();
Monitor.Enter(syncRoot, ref lockWasTaken);
}
public void Exit()
{
if (lockWasTaken)
{
Monitor.Exit(syncRoot);
lockWasTaken = false;
AfterUnlock();
}
}
void BeforeLock()
{
//...
}
void AfterUnlock()
{
//...
}
void IDisposable.Dispose()
{
Exit();
}
}
You could even wrap that in an Extension method and write:
using (foo.Lock())
{
}
Or if you just want to track the attempts at locking the object you could replace
lock(foo) { . . .}
with
lock(TrackLock(foo)) { . . .}
where
public static object TrackLock(object o)
{
Console.WriteLine($"Locking {o.ToString()}");
return o;
}