Existe uma operação “tentar bloquear, pular se o tempo limite expirar” em C#?
-
08-06-2019 - |
Pergunta
Preciso tentar bloquear um objeto e, se já estiver bloqueado, basta continuar (após o tempo limite ou sem ele).
A instrução de bloqueio C# está bloqueando.
Solução
Eu acredito que você pode usar Monitor.TryEnter()
.
A instrução lock apenas se traduz em um Monitor.Enter()
ligue e um try catch
bloquear.
Outras dicas
Ed tem a função certa para você.Só não esqueça de ligar Monitor.Exit()
.Você deve usar um try-finally
bloco para garantir a limpeza adequada.
if (Monitor.TryEnter(someObject))
{
try
{
// use object
}
finally
{
Monitor.Exit(someObject);
}
}
Tive o mesmo problema, acabei criando uma classe TryLock
que implementa IDisposable e então usa o using
instrução para controlar o escopo do bloqueio:
public class TryLock : IDisposable
{
private object locked;
public bool HasLock { get; private set; }
public TryLock(object obj)
{
if (Monitor.TryEnter(obj))
{
HasLock = true;
locked = obj;
}
}
public void Dispose()
{
if (HasLock)
{
Monitor.Exit(locked);
locked = null;
HasLock = false;
}
}
}
E então use a seguinte sintaxe para bloquear:
var obj = new object();
using (var tryLock = new TryLock(obj))
{
if (tryLock.HasLock)
{
Console.WriteLine("Lock acquired..");
}
}
Você provavelmente descobrirá isso por si mesmo agora que os outros apontaram a direção certa, mas o TryEnter também pode usar um parâmetro de tempo limite.
"CLR Via C#" de Jeff Richter é um excelente livro sobre detalhes das entranhas do CLR se você estiver se metendo em coisas mais complicadas.
Considere usar AutoResetEvent e seu método WaitOne com uma entrada de tempo limite.
static AutoResetEvent autoEvent = new AutoResetEvent(true);
if(autoEvent.WaitOne(0))
{
//start critical section
Console.WriteLine("no other thread here, do your job");
Thread.Sleep(5000);
//end critical section
autoEvent.Set();
}
else
{
Console.WriteLine("A thread working already at this time.");
}
Ver https://msdn.microsoft.com/en-us/library/cc189907(v=vs.110).aspx https://msdn.microsoft.com/en-us/library/system.threading.autoresetevent(v=vs.110).aspx e https://msdn.microsoft.com/en-us/library/cc190477(v=vs.110).aspx