Bloqueo con patrón de tiempo de espera

lock usa este patrón

if(Monitor.Enter(lock))
    try
    {
        ...
    }
    finally { Monitor.Exit(lock); } // using this style to reduce post "height"

si no queremos esperar infinito podemos proporcionar tiempo de espera

if(!Monitor.TryEnter(lock, timeout))
    throw new TimeoutException();
try
{
    ...
}
finally { Monitor.Exit(lock); }

Tengo un escenario cuando el método tiene que obtener múltiples bloqueos antes de comenzar a hacer nada. Esto se ve horrible:

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); }

Tiene problemas:

se ve feo (el código del método está sangrado, imagine cómo se verálockZ), se puede resolver poniendo el código del método en otro método.

el bloqueo se produce sincrónicamente, por lo que el peor de los casos exitosos puede demorar un poco menos que la suma de todos los tiempos de espera.

¿Hay alguna manera de mejorar este patrón de tiempo de espera?

Estaba pensando en hacer un método con parámetro delegado y bloqueo para lograr algo como el encadenamiento de linq (pero también ejecutar bloqueos en paralelo, esto es un desafío):

Lock(lockA).Lock(lockB).Lock(lockC).Run( () => ...);

O tal vez hay otra manera?

Respuestas a la pregunta(1)

Su respuesta a la pregunta