Bloqueio com padrão de tempo limite
lock
usa esse padrão
if(Monitor.Enter(lock))
try
{
...
}
finally { Monitor.Exit(lock); } // using this style to reduce post "height"
se não queremos esperar infinito, podemos fornecer tempo limite
if(!Monitor.TryEnter(lock, timeout))
throw new TimeoutException();
try
{
...
}
finally { Monitor.Exit(lock); }
Eu tenho cenário quando o método tem que obter vários bloqueios antes de começar a fazer qualquer coisa. Isso parece horrível:
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); }
Tem problemas:
parece feio (o código do método é recuado, imagine como ele ficarálockZ
), pode ser resolvido colocando o código do método em outro método.
o bloqueio ocorre de forma síncrona, portanto, o pior caso de sucesso pode levar um tempo um pouco menos que a soma de todos os tempos limites.
Existe uma maneira de melhorar esse padrão de tempo limite?
Eu estava pensando em criar um método com parâmetro delegate e lock para obter algo como linq encadeamento (mas também executar bloqueios em paralelo, este é um desafio):
Lock(lockA).Lock(lockB).Lock(lockC).Run( () => ...);
Ou talvez haja outro caminho?