lock
uses this pattern
if(Monitor.Enter(lock))
try
{
...
}
finally { Monitor.Exit(lock); } // using this style to reduce post "height"
if we don't want to wait infinite we can provide timeout
if(!Monitor.TryEnter(lock, timeout))
throw new TimeoutException();
try
{
...
}
finally { Monitor.Exit(lock); }
I have scenario when method has to obtain multiple locks before it start doing anything. This looks awful:
if(!Monitor.TryEnter(lockA, timeout))
throw new TimeoutException();
try
{
if(!Monitor.TryEnter(lockB, timeout))
throw new TimeoutException();
try
{
if(!Monitor.TryEnter(lockC, timeout))
throw new TimeoutException();
try
{
... // more of such constructions
}
finally { Monitor.Exit(lockC); }
}
finally { Monitor.Exit(lockB); }
}
finally { Monitor.Exit(lockA); }
It has problems:
-
looks ugly (the method code is indented, imagine how it will looks for
lockZ
), can be solved by putting method code into another method. -
locking occurs synchronously, so the worst successful case may take time slightly less than a sum of all timeouts.
Is there a way to improve this timeout pattern?
I was thinking to make a method with delegate parameter and lock to achieve something like linq chaining (but to also run locks in parallel, this is a challenge):
Lock(lockA).Lock(lockB).Lock(lockC).Run( () => ...);
Or perhaps there is another way?
Aucun commentaire:
Enregistrer un commentaire