Esiste un'operazione "prova a bloccare, salta se scaduto" in C#?
-
08-06-2019 - |
Domanda
Devo provare a bloccare un oggetto e, se è già bloccato, continuare (dopo il timeout o senza di esso).
L'istruzione lock C# è bloccante.
Soluzione
Credo che tu possa usare Monitor.TryEnter()
.
L'istruzione lock si traduce semplicemente in a Monitor.Enter()
chiamare e a try catch
bloccare.
Altri suggerimenti
Ed ha la funzione giusta per te.Ma non dimenticare di chiamare Monitor.Exit()
.Dovresti usare a try-finally
bloccare per garantire una corretta pulizia.
if (Monitor.TryEnter(someObject))
{
try
{
// use object
}
finally
{
Monitor.Exit(someObject);
}
}
Ho avuto lo stesso problema, ho finito per creare una classe TryLock
che implementa IDisposable e quindi utilizza il file using
istruzione per controllare l'ambito del blocco:
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 quindi utilizzare la seguente sintassi per bloccare:
var obj = new object();
using (var tryLock = new TryLock(obj))
{
if (tryLock.HasLock)
{
Console.WriteLine("Lock acquired..");
}
}
Probabilmente lo scoprirai da solo ora che gli altri ti hanno indicato la giusta direzione, ma TryEnter può anche accettare un parametro di timeout.
"CLR Via C#" di Jeff Richter è un libro eccellente sui dettagli delle parti interne di CLR se ti stai addentrando in cose più complicate.
Prendi in considerazione l'utilizzo di AutoResetEvent e il relativo metodo WaitOne con un input di timeout.
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.");
}
Vedere 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