2009-08-25 20 views
41

Estoy usando el método thread.Abort para matar el hilo, pero no funciona. ¿Hay alguna otra manera de terminar el hilo?¿Cómo matar un hilo instantáneamente en C#?

private void button1_Click(object sender, EventArgs e) 
{ 
    if (Receiver.IsAlive == true) 
    { 
     MessageBox.Show("Alive"); 
     Receiver.Abort(); 
    } 
    else 
    { 
     MessageBox.Show("Dead"); 
     Receiver.Start(); 
    } 
} 

estoy usando esto, pero cada vez que tengo el estado Alive, Receiver es mi hilo global.

+10

Peligro, Will Robinson, Danger! Esté ** muy ** tímido de usar Thread.Abort, casi siempre una mala idea. –

+4

Entonces, ¿qué debería usarse para matar el hilo? – Mobin

+3

Pídale al hilo que se detenga e ignore el hilo a partir de ese momento. – MSalters

Respuesta

58

La razón por la que es difícil matar un hilo es porque los diseñadores del lenguaje quieren evitar el siguiente problema: el hilo se bloquea y luego lo mata antes de poder liberarlo. Ahora cualquiera que necesite ese bloqueo se quedará atascado.

Lo que tienes que hacer es usar alguna variable global para indicar al hilo que se detenga. Usted tiene que manualmente, en su código de hilo, verificar esa variable global y regresar si lo ve que indica que debe detenerse.

+0

Uso este mecanismo yo mismo. Para el código basado en UI, establezco una variable global, y para los servicios verifico una tabla de base de datos. Agradable y predecible. –

+5

Si es posible, use un evento manualResetEvent en lugar de una variable, es para lo que están diseñados. –

+3

Tengo curiosidad ahora: ¿cómo sería el ManualResetEvent superior, para verificar una condición de terminación anticipada? Entiendo que son mejores cuando tenemos que bloquear algo, pero aquí no hay bloqueo. – redtuna

6

El hilo se eliminará cuando termine su trabajo, por lo que si está utilizando bucles u otra cosa, debe pasar variable al hilo para detener el ciclo una vez que el hilo estará terminado.

4

C# Thread.Abort NO se garantiza que aborte el hilo instantáneamente. Probablemente funcione cuando un hilo llama Abort en sí mismo, pero no cuando un hilo llama a otro.

Por favor refiérase a la documentación: http://msdn.microsoft.com/en-us/library/ty8d3wta.aspx

me he enfrentado a este problema herramientas que interactúa con el hardware de la escritura - que desea parada inmediata pero no está garantizada. Normalmente utilizo algunos indicadores u otra lógica para evitar la ejecución de partes de código que se ejecutan en un hilo (y que no quiero que se ejecuten en abortar - complicado).

14

Primero debe tener algún método acordado para finalizar el hilo. Por ejemplo, un running_ valiable que el hilo puede verificar y cumplir.

Su código de subproceso principal debe estar envuelto en un bloque de excepción que capte tanto ThreadInterruptException como ThreadAbortException que limpiarán limpiamente el subproceso al salir.

En el caso de ThreadInterruptException, puede verificar la variable running_ para ver si debe continuar. En el caso de ThreadAbortException, debe ordenar inmediatamente y salir del procedimiento de subprocesos.

El código que trata de impedir que el hilo debe hacer lo siguiente:

running_ = false; 
threadInstance_.Interrupt(); 
if(!threadInstance_.Join(2000)) { // or an agreed resonable time 
    threadInstance_.Abort(); 
} 
+2

Esta es la única respuesta aceptable desde mi punto de vista. Sí, primero necesita una variable para tener en cuenta cuando el hilo puede salir, pero si está bloqueando dentro del hilo, es posible que nunca tenga la oportunidad de verificar esa variable. Es necesario que haya otra forma de interrumpir un hilo bloqueado y esta respuesta resolvió mi problema. ¡Gracias! – CramerTV

+0

Si 'threadInstance_.Interrupt()' termina el subproceso rápido, 'threadInstance_.Join' arrojará * System.Threading.ThreadStateException: El subproceso no se ha iniciado * – Hannobo

24

Se puede matar al instante haciendo de esa manera:

private Thread _myThread = new Thread(SomeThreadMethod); 

private void SomeThreadMethod() 
{ 
    // do whatever you want 
} 

[SecurityPermissionAttribute(SecurityAction.Demand, ControlThread = true)] 
private void KillTheThread() 
{ 
    _myThread.Abort(); 
} 

siempre lo uso y funciona para mí:)

+0

Pero vea http://stackoverflow.com/a/1560567/199364 y otras respuestas que describen por qué thread.abort es arriesgado. – ToolmakerSteve

+2

[La respuesta de Adrian Regan] (http://stackoverflow.com/a/1327377/199364) es una forma MUCHO más segura de utilizar 'Abortar', como último recurso, si un hilo no está muriendo. – ToolmakerSteve

-1
private void ResumeButton_Click(object sender, RoutedEventArgs e) 
    { 
     Task.Factory.StartNew(() => 
     { 
      Application.Current.Resources["AutoPilotThreadStatus"] = true; 
      Thread.CurrentThread.Name = "ResumeAutoPilot"; 
      Thread.CurrentThread.IsBackground = true; 
      AutoPilotHandler.ResumeAutoPilot(); 
     }); 
    } 

    public static void ResumeAutoPilot() 
    { 
     while ((bool)Application.Current.Resources["AutoPilotThreadStatus"]) 
     { 
      CheckAutoPilotThreadStatus(); 
      var searchYoutube = YoutubeHandler.Search("small truck"); 
      CheckAutoPilotThreadStatus(); 
      SaveVideosToDatabase(searchYoutube); 
      CheckAutoPilotThreadStatus(); 
     } 
    } 

    public static void CheckAutoPilotThreadStatus() 
    { 
     if (!(bool)Application.Current.Resources["AutoPilotThreadStatus"]) 
     { 
      KillCurrentThread(); 
     } 
    } 

    public static void KillCurrentThread() 
    { 
     Thread.CurrentThread.Abort(); 
    } 
+3

Un ejemplo perfecto de cómo los recursos de la aplicación no se deben utilizar. –