2009-08-25 6 views
41

J'utilise la méthode thread.Abort pour supprimer le thread, mais cela ne fonctionne pas. Y a-t-il un autre moyen de terminer le fil?Comment tuer un fil instantanément 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(); 
    } 
} 

J'utilise cela, mais chaque fois que je reçois le statut Alive, Receiver est mon fil global.

+10

Danger, Will Robinson, Danger! Soyez ** très ** timide d'utiliser Thread.Abort - presque toujours une mauvaise idée. –

+4

Alors qu'est-ce qui devrait être utilisé pour tuer le fil? – Mobin

+3

Demandez au thread d'arrêter et d'ignorer le thread à partir de ce moment. – MSalters

Répondre

58

La raison pour laquelle il est difficile de tuer un thread est que les concepteurs de langage veulent éviter le problème suivant: votre thread prend un verrou, puis vous le tuez avant de pouvoir le libérer. Maintenant, toute personne qui a besoin de ce verrou sera coincé.

Ce que vous avez à faire est d'utiliser une variable globale pour dire au thread de s'arrêter. Vous devez manuellement, dans votre code de thread, vérifier cette variable globale et retourner si vous le voyez indique que vous devriez arrêter.

+0

J'utilise ce mécanisme moi-même. Pour le code basé sur l'interface utilisateur, je définis une variable globale et, pour les services, je vérifie une table de base de données. Agréable et prévisible. –

+5

Si possible, utilisez un ManualResetEvent au lieu d'une variable, c'est pour quoi ils sont conçus. –

+3

Je suis curieux maintenant - comment le ManualResetEvent serait-il supérieur, pour vérifier une condition de fin anticipée? Je comprends qu'ils sont meilleurs quand nous devons bloquer quelque chose, mais il n'y a pas de blocage ici. – redtuna

6

thread sera détruit quand il finira son travail, donc si vous utilisez des boucles ou autre chose, vous devez passer variable au thread pour arrêter la boucle après que le thread sera terminé.

4

C# Thread.Abort n'est pas garanti pour annuler le thread instantanément. Cela fonctionnera probablement quand un thread appelle Abort sur lui-même mais pas quand un thread appelle un autre.

S'il vous plaît se référer à la documentation: http://msdn.microsoft.com/en-us/library/ty8d3wta.aspx

J'ai fait face à ce problème d'écriture des outils qui interagissent avec le matériel - vous voulez arrêt immédiat mais il est pas garanti. J'utilise généralement des drapeaux ou d'autres logiques pour empêcher l'exécution de parties de code s'exécutant sur un thread (et que je ne veux pas exécuter sur avortement).

14

Vous devez d'abord avoir une méthode convenue pour terminer le thread. Par exemple run_ valiable que le thread peut vérifier et respecter.

Votre code thread principal doit être enveloppé dans un bloc d'exception qui attrape à la fois ThreadInterruptException et ThreadAbortException qui nettoiera proprement le thread à la sortie.

Dans le cas de ThreadInterruptException, vous pouvez vérifier la variable running_ pour voir si vous devez continuer. Dans le cas de ThreadAbortException, vous devez ranger immédiatement et quitter la procédure de thread.

Le code qui tente d'arrêter le fil doit faire ce qui suit:

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

C'est la seule réponse acceptable de mon point de vue. Oui, vous devez d'abord avoir une variable pour noter quand le thread peut quitter mais si vous bloquez dans le thread, vous ne pourrez peut-être jamais vérifier cette variable. Il doit y avoir une autre façon d'interrompre un thread qui est bloqué et cette réponse a résolu mon problème. Merci! – CramerTV

+0

Si 'threadInstance_.Interrupt()' termine le thread rapidement, 'threadInstance_.Join' lancera * System.Threading.ThreadStateException: Le thread n'a pas été démarré * – Hannobo

24

Vous pouvez le tuer faire instantanément de cette façon:

private Thread _myThread = new Thread(SomeThreadMethod); 

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

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

Je l'utilise toujours et fonctionne pour moi:

+0

Mais voir http://stackoverflow.com/a/1560567/199364 , et d'autres réponses décrivant pourquoi thread.abort est risqué. – ToolmakerSteve

+2

[La réponse d'Adrian Regan] (http://stackoverflow.com/a/1327377/199364) est BEAUCOUP plus sûr d'utiliser 'Abort' - en dernier recours si un thread ne meurt pas. – 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 exemple parfait de la façon dont les ressources de l'application ne doivent pas être utilisées. –

Questions connexes