Aquí podría ser tu PUBLICIDAD


En C # ¿cómo puedo salir con seguridad de un bloqueo con un bloque try catch dentro?

votos
14

Aquí hay un ejemplo de una excepción que ocurre dentro de un bloqueo, con un bloque try-catch.

int zero = 0;
int j = 10;

lock (sharedResource.SyncRoot)
{
    try
    {
        j = j / zero;
    }
    catch (DivideByZeroException e)
    {
        // exception caught but lock not released
    }
}

¿Cómo desbloqueo este candado con seguridad?

Publicado el 12/03/2009 a las 17:47
fuente por usuario Justin Tanner
En otros idiomas...        العربية       

7 respuestas

votos
35

¿No se lanzará automáticamente?

Desde el medio de bloqueo de MSDN

System.Threading.Monitor.Enter(x);
try {
   ...
}
finally {
   System.Threading.Monitor.Exit(x);
}

Entonces no tienes que molestarte.

Respondida el 12/03/2009 a las 05:50
fuente por usuario Mykola Golubyev


Aquí podría ser tu PUBLICIDAD


votos
13

El bloqueo no se liberará hasta que salga del alcance del bloque de bloqueo (sharedResource.SyncRoot). lock (sharedResource.SyncRoot) {}es básicamente idéntico a:

Monitor.Enter(sharedResource.SyncRoot);
try
{
}
finally
{
    Monitor.Exit(sharedResource.SyncRoot);
}

Puede hacer la entrada / salida usted mismo si desea más control, o simplemente hacer que el bloqueo se ajuste a lo que desea, como:

try
{
    lock(sharedResource.SyncRoot)
    {
        int bad = 2 / 0;
    }
}
catch (DivideByZeroException e)
{
   // Lock released by this point.
}
Respondida el 12/03/2009 a las 05:55
fuente por usuario Michael

votos
6

Prueba.

.method public hidebysig instance void  test(int32 i) cil managed
{
  // Code size       43 (0x2b)
  .maxstack  2
  .locals init ([0] int32 bad,
           [1] class [mscorlib]System.DivideByZeroException e,
           [2] object CS$2$0000)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  ldfld      object WebApplication1.myclass::mutex
  IL_0007:  dup
  IL_0008:  stloc.2
  IL_0009:  call       void [mscorlib]System.Threading.Monitor::Enter(object)
  IL_000e:  nop
  .try
  {
    IL_000f:  nop
    .try
    {
      IL_0010:  nop
      IL_0011:  ldc.i4.2
      IL_0012:  ldarg.1
      IL_0013:  div
      IL_0014:  stloc.0
      IL_0015:  nop
      IL_0016:  leave.s    IL_001d
    }  // end .try
    catch [mscorlib]System.DivideByZeroException 
    {
      IL_0018:  stloc.1
      IL_0019:  nop
      IL_001a:  nop
      IL_001b:  leave.s    IL_001d
    }  // end handler
    IL_001d:  nop
    IL_001e:  nop
    IL_001f:  leave.s    IL_0029
  }  // end .try
  finally
  {
    IL_0021:  ldloc.2
    IL_0022:  call       void [mscorlib]System.Threading.Monitor::Exit(object)
    IL_0027:  nop
    IL_0028:  endfinally
  }  // end handler
  IL_0029:  nop
  IL_002a:  ret
} // end of method myclass::test
Respondida el 12/03/2009 a las 06:02
fuente por usuario annakata

votos
4

Jaredpar publicó un enlace en un comentario que creo que vale la pena echarle un vistazo:

http://blogs.msdn.com/ericlippert/archive/2009/03/06/locks-and-exceptions-do-not-mix.aspx

En esta publicación de blog Eric Lippert comenta sobre los problemas relacionados con el bloqueo en C #:

El problema aquí es que si el compilador genera una instrucción no operativa entre la entrada de monitor y la región de prueba protegida, es posible que el tiempo de ejecución arroje una excepción de interrupción de hilo después de que el monitor ingrese pero antes de la prueba. En ese escenario, el finalmente nunca se ejecuta, por lo que la cerradura pierde, probablemente bloqueando el programa. Sería bueno si esto fuera imposible en versiones optimizadas y no optimizadas.

Respondida el 12/03/2009 a las 08:43
fuente por usuario Justin Tanner

votos
2

Tu código está perfectamente bien. El lock(sth){...}se traduce internamente a un try finallybloque.

Respondida el 12/03/2009 a las 05:55
fuente por usuario Grzenio

votos
1

El bloqueo se liberará cuando se salga del contexto de su bloqueo, sin embargo, eso sucede. En el ejemplo de código dado anteriormente, el bloqueo se liberará de manera segura y automática cuando el control abandone el contexto final.

Respondida el 12/03/2009 a las 05:53
fuente por usuario Jeff Kotula

votos
1

¿No funcionaría así sin tener en cuenta?

try
{
  lock (sharedResource.SyncRoot)
  {
      int bad = 2 / 0;
  }
}
catch (DivideByZeroException e)
{
    // exception caught but lock not released
}
finally
{
      //release lock
}
Respondida el 12/03/2009 a las 05:51
fuente por usuario cgreeno