start - c#.net threading
¿Cómo puedo detectar una ThreadAbortException en un bloque finally?(.RED) (7)
De hecho, puedes ejecutar código en la instrucción catch para una ThreadAbortException. El problema es que la excepción se volverá a ejecutar una vez que la ejecución abandone el bloque catch.
Si realmente desea evitar que la excepción continúe, puede llamar a Thread.ResetAbort (). Sin embargo, esto requiere confianza total y, a menos que tenga un escenario específico, es casi seguro que no es lo correcto.
Tengo una lógica crítica en un bloque finally (con un bloque try vacío), porque quiero garantizar que el código se ejecute incluso si el hilo se cancela. Sin embargo, también me gustaría detectar ThreadAbortException. Descubrí que al envolver mi bloque try / finally crítico en try / catch no se detecta ThreadAbortException. ¿Hay alguna forma de detectarlo?
try { try { } finally { // critical logic } } catch(Exception ex) { // ThreadAbortException is not caught here, but exceptions thrown // from within the critical logic are }
Lea sobre las regiones de ejecución restringida .
Específicamente, el método RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup será útil aquí.
No creo que sea posible.
¿Por qué necesita manejar ThreadAbortException en primer lugar? Hilo de llamada.Abort () suele ser un signo de mal diseño. Tener una variable de indicador que cuando se establece en verdadero simplemente regresará; desde la función de hilo, después de la limpieza adecuada, por supuesto.
De esta forma, no tendrá que preocuparse por la excepción.
Estoy de acuerdo con Arul. Calling Thread.Abort () es un signo de mal diseño.
Permítanme citar a Peter Ritchie de MSDN: Thread.Abort (el énfasis es mío):
Hay muchas razones para no usar Thread.Abort y ThreadAbortException
En ciertas plataformas (como x64 e IA64) el aborto puede ocurrir antes de que Monitor.Enter y un bloque try (incluso con lock / SyncLock), dejando el monitor huérfano. ThreadAbortException puede ocurrir en código de terceros no escrito para manejar el aborto de subprocesos. El hilo se puede cancelar mientras se procesa un bloque finally en .NET 1.x. Utiliza excepciones para la lógica de flujo de control normal. La excepción asíncrona puede interrumpir la modificación del estado o los recursos del fragmento, dejándolos dañados.
Para más detalles ver:
http://msmvps.com/blogs/peterritchie/archive/2007/08/22/thead-abort-is-a-sign-of-a-poorly-designed-program.aspx
http://www.bluebytesoftware.com/blog/2007/01/30/MonitorEnterThreadAbortsAndOrphanedLocks.aspx
http://blogs.msdn.com/ericlippert/archive/2007/08/17/subtleties-of-c-il-codegen.aspx
¿Has intentado algo como ésto?
try {
try { }
catch (ThreadAbortException)
{
ThreadAbortExceptionBool = true;
}
finally {
// critical logic
if (ThreadAbortExceptionBool)
// Whatever
}
}
catch(Exception ex) {
// ThreadAbortException is not caught here, but exceptions thrown
// from within the critical logic are
}
Este es un problema curioso.
El código que publicaste debería funcionar. Parece que hay algún tipo de optimización que decide no llamar a su controlador de captura.
Entonces, quería detectar la excepción con esto:
bool threadAborted = true;
try {
try { }
finally { /* critical code */ }
threadAborted = false;
}
finally {
Console.WriteLine("Thread aborted? {0}", threadAborted);
}
Console.WriteLine("Done");
(Mi código real simplemente dormía en esa sección de código crítico, así que podría estar seguro de que abortaría finalmente después de eso).
Imprimió:
Hilo abortado? Falso
Hmmm, ¡extraño de verdad!
Así que pensé en hacer un poco más de trabajo allí, para engañar a cualquier optimización "inteligente":
bool threadAborted = true;
try {
try { }
finally { /* critical code */ }
threadAborted = AmIEvil();
}
finally {
Console.WriteLine("Thread aborted? {0}", threadAborted);
}
Console.WriteLine("Done");
Donde AmIEvil
es justo:
[MethodImpl(MethodImplOptions.NoInlining)]
static bool AmIEvil() {
return false;
}
Finalmente imprimió:
Hilo abortado? Cierto
Y ahí lo tienes. Use esto en su código:
try {
try { }
finally { /* critical code */ }
NoOp();
}
catch (Exception ex) {
// ThreadAbortException is caught here now!
}
Donde NoOp
es solo:
[MethodImpl(MethodImplOptions.NoInlining)]
static void NoOp() { }
Si llamar a Thread.Abort es un mal diseño, ¿por qué SQL Server lo llama en un hilo que ejecuta el código de usuario? Porque así es exactamente como se maneja una cancelación de consulta y causa pesadillas.