Domanda

Devo provare a bloccare un oggetto e, se è già bloccato, continuare (dopo il timeout o senza di esso).

L'istruzione lock C# è bloccante.

È stato utile?

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top