¿Existe una operación de "intentar bloquear, omitir si se agota el tiempo de espera" en C#?

StackOverflow https://stackoverflow.com/questions/8546

  •  08-06-2019
  •  | 
  •  

Pregunta

Necesito intentar bloquear un objeto y, si ya está bloqueado, continuar (después del tiempo de espera o sin él).

La declaración de bloqueo de C# está bloqueando.

¿Fue útil?

Solución

Creo que puedes usar Monitor.TryEnter().

La declaración de bloqueo simplemente se traduce en una Monitor.Enter() llamada y un try catch bloquear.

Otros consejos

Ed tiene la función adecuada para ti.No olvides llamar Monitor.Exit().Deberías usar un try-finally bloque para garantizar una limpieza adecuada.

if (Monitor.TryEnter(someObject))
{
    try
    {
        // use object
    }
    finally
    {
        Monitor.Exit(someObject);
    }
}

Tuve el mismo problema, terminé creando una clase. TryLock que implementa IDisposable y luego usa el using Declaración para controlar el alcance del bloqueo:

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

Y luego use la siguiente sintaxis para bloquear:

var obj = new object();

using (var tryLock = new TryLock(obj))
{
    if (tryLock.HasLock)
    {
        Console.WriteLine("Lock acquired..");
    }
}

Probablemente lo descubrirá usted mismo ahora que los demás le han indicado la dirección correcta, pero TryEnter también puede tomar un parámetro de tiempo de espera.

"CLR Via C#" de Jeff Richter es un libro excelente sobre los detalles de las entrañas de CLR si te adentras en temas más complicados.

Considere usar AutoResetEvent y su método WaitOne con una entrada de tiempo de espera.

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 y https://msdn.microsoft.com/en-us/library/cc190477(v=vs.110).aspx

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top