2008-08-12 25 views

Respuesta

34

Creo que puede usar Monitor.TryEnter().

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

+0

¿Qué pasa si estoy tratando con la concurrencia entre procesos? ¿Hay alguna forma de usar un Mutex de manera similar? –

80

Ed tiene la función adecuada para usted. No olvides llamar al Monitor.Exit(). Debe usar un bloque try-finally para garantizar una limpieza adecuada.

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

+1, gracias! Propuso un pequeño cambio, si lo desea, para recordarle que (casi) siempre es posible usar constructos/patrones avanzados sin anclar llaves indefinidamente. – ceztko

+0

@ceztko, ¿puedes aclarar? En general, la liberación de N recursos en, por ejemplo, C# requiere N bloques try-finally anidados. La instrucción using ayuda a evitar esto solo para IDisposables. Saltarse los bloques try-finally puede dar como resultado la fuga de recursos en el caso de una excepción. Por ejemplo, la documentación [Monitor] (http://msdn.microsoft.com/en-us/library/aa720302 (v = VS.71) .aspx) aclara que el bloque finally es necesario. Extrañamente, el vínculo de Ed lo descuida. –

3

Es probable que encuentres esto por ti mismo ahora que los demás se han señalado en 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 excelente libro sobre los detalles de las entrañas de CLR si te estás metiendo en cosas más complicadas.

10

que tenían el mismo problema, que acabó creando una clase TryLock que implementa IDisposable y luego utiliza la sentencia using para controlar el alcance de la cerradura:

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 a continuación, utilizar la siguiente sintaxis para bloquear:

var obj = new object(); 

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