Terminación de subproceso de C # y Thread.Abort ()

85

En MSDN, la descripción del método Thread.Abort () dice: "Llamar a este método normalmente termina el hilo".

¿Por qué no SIEMPRE?

¿En qué casos no termina el hilo?

¿Existe alguna otra posibilidad de terminar los hilos?

user101375
fuente

Respuestas:

60

Thread.Abort()inyecta un ThreadAbortExceptionen el hilo. El hilo puede cancelar la solicitud llamando Thread.ResetAbort(). Además, hay ciertas partes del código, como el finallybloque, que se ejecutará antes de que se maneje la excepción. Si por alguna razón el hilo se atasca en dicho bloque, la excepción nunca se generará en el hilo.

Como la persona que llama tiene muy poco control sobre el estado del hilo al llamar Abort(), generalmente no es aconsejable hacerlo. En su lugar, pasa un mensaje al hilo solicitando la terminación.

Brian Rasmussen
fuente
¿Qué tipo de mensaje? ¿Te refieres a la invocación de un método?
user101375
4
Eso depende de cómo pase los datos entre sus hilos. Por ejemplo, si su hilo es un hilo de trabajo con una cola de tareas, puede poner en cola un mensaje PleaseTerminate y dejar que el hilo lo maneje con elegancia.
Brian Rasmussen
Mi hilo tiene un gran problema que puede resolverse, no hay cola de tareas.
user101375
Como dije, depende de cómo esté diseñado su código de hilo. Quizás pueda entonces señalar a través de una variable miembro. Es difícil ser más específico sin el código real disponible.
Brian Rasmussen
54

¿En qué casos no termina el hilo?

Esta pregunta es un duplicado.

¿Qué hay de malo en usar Thread.Abort ()?

¿Existe alguna otra posibilidad para terminar los hilos?

Si. Su problema es que nunca debe iniciar un hilo al que no pueda decirle cortésmente que se detenga, y se detiene de manera oportuna. Si se encuentra en una situación en la que tiene que iniciar un hilo que podría ser (1) difícil de detener, (2) con errores, o lo peor de todo (3) hostil al usuario, entonces lo correcto es hacer un nuevo proceso, inicie el subproceso en el nuevo proceso y luego finalice el proceso cuando desee que el subproceso baje. Lo único que puede garantizar la terminación segura de un hilo que no coopera es que el sistema operativo elimine todo su proceso.

Vea mi respuesta excesivamente larga a esta pregunta para obtener más detalles:

Uso de la declaración de bloqueo dentro de un bucle en C #

El bit relevante es el bit al final donde discuto cuáles son las consideraciones con respecto a cuánto tiempo debe esperar a que un hilo se mate antes de abortarlo.

Eric Lippert
fuente
Eric, ¿cómo debería decirle cortésmente a un hilo que se detenga si ese hilo está esperando en un objeto de sincronización, por ejemplo, EventWaitHandle.WaitOne () ;?
Corvin
5
@Corvin: el contrato entre dos subprocesos que describe cómo un subproceso debe comunicarse con otro depende de los autores del código que se ejecuta en esos subprocesos. Si tiene requisitos que (1) un subproceso X debe esperar en un objeto potencialmente para siempre, y (2) ese subproceso Y debe poder cerrar limpiamente el subproceso X en una cantidad finita de tiempo, entonces creo que tiene requisitos contradictorios; decide cuál gana. Si es lo primero, entonces el hilo Y tendrá que esperar. Si es lo último, entonces el hilo X no debería estar esperando para siempre, debería esperar una pequeña cantidad de tiempo.
Eric Lippert
Gracias por responder. Considere la siguiente arquitectura: tengo una aplicación que tiene que minimizarse cuando ocurre un determinado evento en todo el sistema. Tengo un hilo en esa aplicación que espera un evento con nombre global y hace su trabajo cuando se establece ese evento. Por otro lado, mi aplicación puede tener que cerrarse antes de que ocurra el evento, teniendo que cerrar ese hilo de espera. ¿Cuál es la forma samurái de codificar tal cosa?
Corvin
@Corvin: Podría tener un bucle que espera (con un tiempo de espera corto) el evento, luego verifica si debe dejar de intentar esperar (para que pueda salir normalmente). De esta manera, puede indicarle a su hilo que debe detenerse, y solo debe esperar el tiempo de espera para que se detenga.
Kevin Kibler
2
@Corvin, si convierte ese hilo en espera en un hilo en segundo plano, no debería tener que cerrarlo antes de que se cierre la aplicación.
Don Kirkby
17

¿Por qué no SIEMPRE? ¿En qué casos no termina el hilo?

Para empezar, un hilo puede atrapar ThreadAbortExceptionay cancelar su propia terminación. O podría realizar un cálculo que lleva una eternidad mientras intentas abortarlo. Debido a esto, el tiempo de ejecución no puede garantizar que el hilo siempre terminará después de que usted lo solicite.

ThreadAbortException tiene mas:

Cuando se realiza una llamada al método Abort para destruir un hilo, Common Language Runtime lanza una ThreadAbortException. ThreadAbortException es una excepción especial que se puede capturar, pero se generará de nuevo automáticamente al final del bloque de captura. Cuando se genera esta excepción, el tiempo de ejecución ejecuta todos los bloques finalmente antes de finalizar el hilo. Dado que el hilo puede hacer un cálculo ilimitado en los bloques finalmente, o llamar Thread.ResetAbort()para cancelar el aborto, no hay garantía de que el hilo termine alguna vez.

No necesitas Abort()un hilo manualmente. El CLR hará todo el trabajo sucio por usted si simplemente deja que el método en el hilo regrese; que terminará el hilo normalmente.

John Feminella
fuente
Necesito Abortarlo (), debido a que se inició un bucle de mensaje en ese hilo (Dispatcher.Run ();). Si lo entiendo correctamente, ¿necesito invocar un método que llame a return en el hilo para terminarlo?
user101375
7

FileStream.Read()a una tubería con nombre que actualmente no recibe nada (leer bloques de llamadas mientras espera datos entrantes) no responderá Thread.Abort(). Permanece dentro de la Read()llamada.

Jovain
fuente
6

¿Qué pasa si un hilo está bloqueado y se aborta / mata? Los recursos permanecen estancados

Funciona bien cuando un hilo llama a abortarse pero no por otro hilo. Abortar, termina forzosamente el subproceso afectado incluso si no ha completado su tarea y no brinda ninguna oportunidad para la limpieza de recursos

referencia MSDN


consulte: Prácticas recomendadas de subprocesos administrados

Asad
fuente
5

Parece que no puedo abortar un hilo que está atascado en un bucle:

//immortal
Thread th1 = new Thread(() => { while (true) {}});

Sin embargo, puedo abortar el hilo si duerme durante el ciclo:

//mortal
Thread th2 = new Thread(() => { while (true) { Thread.Sleep(1000); }});
Colin
fuente
1
esto no parece ser cierto, ejecuté un programa de prueba: `{var th = new Thread (() => {int i = 0; try {while (true) {i ++;}} catch (Exception e) { Console.WriteLine ("abortando @ {0}", i);}}); th.Start (); Thread.Sleep (1000); th.Abort (); th.Unirse (); }
Weipeng L
3

Porque puedes atrapar ThreadAbortExceptiony llamar Thread.ResetAbortdentro del controlador.

erikkallen
fuente
0

OT: Para obtener una versión completa, independiente del lenguaje, cuestionablemente útil y muy divertida de la concurrencia, consulte Verity Stob .

Pontus Gagge
fuente
-1

He tenido casos en los que el hilo ha estado demasiado ocupado para escuchar la llamada Abort (), lo que generalmente da como resultado que se lanza una ThreadAbortingException a mi código.

Andy Shellam
fuente