2010-02-12 20 views
75

En MSDN, la descripción del método Thread.Abort() dice: "Llamar a este método generalmente finaliza el subproceso".C# Terminación de subproceso y Thread.Abort()

¿Por qué no SIEMPRE?

¿En qué casos no termina el hilo?

¿Hay alguna otra posibilidad de terminar subprocesos?

Respuesta

15

¿Por qué no ALWAYS? ¿En qué casos no termine el hilo?

Para los iniciadores, un hilo puede atrapar un ThreadAbortException y cancelar su propia terminación. O podría realizar un cálculo que demora para siempre mientras intentas abortarlo. Debido a esto, el tiempo de ejecución no puede garantizar que el hilo siempre terminará después de que se lo solicite.

ThreadAbortException tienen más información:

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

No necesita Abort() un hilo manualmente. El CLR hará todo el trabajo sucio por ti si simplemente dejas que el método en el hilo vuelva; eso terminará el hilo normalmente

+0

me necesita abortar(), debido a un bucle de mensaje iniciado en ese hilo (Dispatcher.Run();). Si lo entiendo correcto, ¿debo invocar un método que llame a return en el hilo para finalizarlo? – user101375

-1

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

5

¿Qué pasa si un hilo está presionando un candado y se cancela/mata? Los recursos permanecen atascados

Funciona bien cuando un hilo llama a se cancela pero no por otro hilo. Abortar, fuerza termina la hilo afectados, incluso si no ha completado su tarea y no proporciona oportunidad para la limpieza de recursos

referencia MSDN


véase: Managed Threading Best Practices

51

Thread.Abort() inyecta un ThreadAbortException en el hilo. El hilo puede cancelar la solicitud llamando al Thread.ResetAbort(). Además, hay ciertas partes del código, como el bloque finally que se ejecutará antes de que se maneje la excepción. Si por algún motivo el hilo queda atascado en dicho bloque, la excepción nunca se levantará en el hilo.

Como la persona que llama tiene muy poco control sobre el estado de la secuencia al llamar al Abort(), generalmente no es aconsejable hacerlo. Pase un mensaje al hilo que solicita la terminación en su lugar.

+0

¿Qué tipo de mensaje? ¿Te refieres a una invocación de método? – user101375

+4

Eso depende de cómo pasa los datos entre sus hilos. P.ej. si el hilo es un hilo de trabajo con una cola de tareas, puede poner en cola un mensaje por favor terminar y dejar que el hilo lo maneje con gracia. –

+0

Mi hilo tiene un gran problema que se resuelve el mástil, si no hay cola de tareas. – user101375

0

OT: ¡Para obtener una perspectiva general, independiente del idioma, cuestionablemente útil y zurcida sobre la simultaneidad, vea Verity Stob!

3

Debido a que se puede coger el ThreadAbortException y llame Thread.ResetAbort dentro del manejador.

46

¿En qué casos no termina la rosca?

Esta pregunta es un duplicado.

What's wrong with using Thread.Abort()

¿Hay alguna otra posibilidad de interrumpir las discusiones?

Sí. Tu problema es que nunca debes poner en marcha un hilo que no puedes decir educadamente que pare, y se detiene de manera oportuna. Si se encuentra en una situación en la que tiene que iniciar un hilo que puede ser (1) difícil de detener, (2) defectuoso, o lo peor de todo (3) hostil para el 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 descienda. Lo único que puede garantizar la finalización segura de un hilo no cooperativo es que el sistema operativo anule todo el proceso.

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

Using lock statement within a loop in C#

El bit relevante es el bit en el extremo donde discuto lo que las consideraciones están en relación con el tiempo que debe esperar a que un hilo suicidarse antes de abortarlo

+0

Eric, ¿cómo debo decirle educadamente a un hilo detenerse si ese hilo está esperando en un objeto de sincronización, p. EventWaitHandle.WaitOne() ;? – Corvin

+5

@ Corvin: el contrato entre dos hilos que describe cómo un hilo se va a comunicar con otro depende de los autores del código que se ejecuta en esos hilos. Si tiene requisitos que (1) un hilo X debe esperar en un objeto potencialmente para siempre, y (2) ese hilo Y debe poder cerrar limpiamente el hilo X en un período finito de tiempo, entonces creo que tiene requisitos contradictorios; decide cuál gana. Si el primero, entonces el hilo Y tendrá que esperar. Si es este último, entonces el hilo X no debería esperar para siempre, debería esperar una pequeña cantidad de tiempo. –

+0

Gracias por responder. Considere la siguiente arquitectura: Tengo una aplicación que tiene que minimizarse cuando ocurre un cierto evento en todo el sistema. Tengo un hilo en esa aplicación que espera en un evento nombrado global y funciona cuando ese evento está configurado. Por otro lado, mi aplicación puede tener que cerrar antes de que ocurra el evento, teniendo que cerrar ese hilo de espera. ¿Cuál es la forma samurai de codificar tal cosa? – Corvin

6

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

2

Me parece que no puede abortar un hilo que se ha quedado atascado en un bucle:

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

puedo embargo abortar el hilo si duerme durante el bucle:

//mortal 
Thread th2 = new Thread(() => { while (true) { Thread.Sleep(1000); }}); 
Cuestiones relacionadas