web-dev-qa-db-fra.com

Tuer un thread .NET

J'ai créé un fil exécutant une certaine méthode. Mais parfois, je voudrais tuer le fil même s'il fonctionne toujours. Comment puis-je faire ceci? J'ai essayé Thread.Abort () mais il affiche une boîte de message disant "Thread aborted". Que devrais-je faire?

19
Jorge Branco

N'appelez pas Thread.Abort()!

Thread.Abort Est dangereux. Au lieu de cela, vous devez coopérer avec le fil afin qu'il puisse être arrêté pacifiquement. Le thread doit être conçu de manière à pouvoir lui dire de se tuer, par exemple en ayant un indicateur booléen keepGoing que vous définissez sur false lorsque vous voulez que le thread s'arrête. Le fil aurait alors quelque chose comme

while (keepGoing)
{
    /* Do work. */
}

Si le thread peut bloquer dans un Sleep ou Wait alors vous pouvez le séparer de ces fonctions en appelant Thread.Interrupt() . Le thread doit alors être préparé pour gérer un ThreadInterruptedException:

try
{
    while (keepGoing)
    {
        /* Do work. */
    }
}
catch (ThreadInterruptedException exception)
{
    /* Clean up. */
}
48
John Kugelman

Vous ne devriez vraiment appeler Abort () qu'en dernier recours. Vous pouvez utiliser une variable pour synchroniser ce fil à la place:

volatile bool shutdown = false;

void RunThread()
{
   while (!shutdown)
   {
      ...
   }
}

void StopThread()
{
   shutdown = true;
}

Cela permet à votre thread de terminer proprement ce qu'il faisait, laissant votre application dans un bon état connu.

26
Jon B

Le moyen le plus correct et le plus sûr pour les threads est d'utiliser un WaitHandle pour signaler au thread quand il est censé s'arrêter. J'utilise principalement ManualResetEvent.

Dans votre fil, vous pouvez avoir:

private void RunThread()
{
    while(!this.flag.WaitOne(TimeSpan.FromMilliseconds(100)))
    {
        // ...
    }
}

this.flag est une instance de ManualResetEvent. Cela signifie que vous pouvez appeler this.flag.Set() depuis l'extérieur du thread pour arrêter la boucle.

La méthode WaitOne ne renvoie true que lorsque l'indicateur est défini. Sinon, il expirera après le délai spécifié (100 ms dans l'exemple) et le thread s'exécutera à nouveau dans la boucle.

9
Mark Seemann

Ce n'est pas une bonne idée de tuer un fil. Il vaut mieux signaler qu'il doit s'arrêter et se terminer avec élégance. Il existe différentes façons de procéder.

  • Utilisation Thread.Interrupt pour le pousser s'il est bloqué.
  • Sondez une variable indicateur.
  • Utilisez la classe WaitHandle pour envoyer un signal.

Il n'est pas nécessaire pour moi de ressasser la façon dont chaque méthode peut être utilisée puisque je l'ai déjà fait dans cette réponse .

7
Brian Gideon

L'abandon d'un thread est une très mauvaise idée, car vous ne pouvez pas déterminer ce que le thread faisait au moment de l'interruption.

Au lieu de cela, disposez d'une propriété que le thread peut vérifier et que votre code externe peut définir. Laissez le thread vérifier cette propriété booléenne lorsqu'il se trouve dans un endroit sûr pour quitter.

2
John Saunders

J'accepte Jon B

volatile bool shutdown = false;

void RunThread()
{

try
{
    while (!shutdown)
    {
        /* Do work. */
    }
}
catch (ThreadAbortException exception)
{
    /* Clean up. */
}
}

void StopThread()
{
   shutdown = true;
}
2
XenKid

Il y a aussi des exemples de tuer des threads dans ma classe WebServer ...

https://net7ntcip.codeplex.com/SourceControl/changeset/view/89621#1752948

Je dirais que l'abandon est correct, comprenez simplement quelles sont les ramifications ... tant que vous indiquez l'état avant qu'une tâche de longue durée ne fonctionne, mais des indicateurs sont requis tels que (ShouldStop ou ActionBranch, etc.)

Consultez-le pour des exemples!

1
Jay