Destruction des threads

Pour mettre fin à l’exécution du thread, on utilise généralement le modèle d’annulation coopérative. Toutefois, il n’est pas possible d’arrêter de manière coopérative un thread qui exécute du code tiers non conçu pour l’annulation coopérative. Dans les applications .NET Framework, vous pouvez utiliser la méthode Thread.Abort pour forcer l’arrêt d’un thread managé. Quand vous appelez Abort, le Common Language Runtime lève une exception ThreadAbortException dans le thread cible, que ce dernier peut intercepter (toutefois, le runtime .NET Framework renvoie toujours l’exception automatiquement après le bloc catch). Pour plus d’informations, consultez Thread.Abort.

La méthode Thread.Abortn’est pas prise en charge dans .NET 5 (y compris .NET Core) ni les versions ultérieures. Si vous devez forcer l’arrêt de l’exécution d’un code tiers dans .NET 5 (ou une version ultérieure), exécutez-le dans le processus distinct et utilisez Process.Kill.

Notes

  • Lorsque vous appelez Thread.Abort pour abandonner un thread autre que le thread actuel, vous ne savez pas quel code s’est exécuté ou n’a pas pu s’exécuter lorsque ThreadAbortException est levée. Vous ne pouvez pas non plus être certain de l’état de votre application ni de l’état de toute application et de l’utilisateur qu’elle doit préserver. Par exemple, l’appel de Thread.Abort peut empêcher l’exécution de constructeurs statiques ou la libération de ressources managées ou non managées.
  • Si un thread est en train d’exécuter du code non managé quand sa méthode Abort est appelée, le runtime le marque comme ThreadState.AbortRequested. L’exception est levée quand le thread retourne au code managé.

Une fois un thread annulé, il ne peut pas être redémarré.

La méthode Abort n’entraîne pas l’annulation immédiate du thread, car le thread cible peut intercepter l’exception ThreadAbortException et exécuter arbitrairement des quantités de code dans un bloc finally. Vous pouvez appeler Thread.Join si vous devez attendre que le thread se termine. Thread.Join est un appel bloquant qui ne retourne de résultats que quand le thread a réellement arrêté son exécution ou qu’un intervalle de délai d’attente facultatif a expiré. Le thread annulé pourrait appeler la méthode ResetAbort ou exécuter un traitement illimité dans un bloc finally. Par conséquent, si vous ne spécifiez pas de délai d’attente, l’attente pourrait ne jamais se terminer.

Les threads qui attendent suite à un appel à la méthode Thread.Join peuvent être interrompus par d’autres threads qui appellent Thread.Interrupt.

Gestion de ThreadAbortException

Si vous pensez que votre thread sera annulé, soit suite à un appel de votre propre code à Abort, soit suite au déchargement d’un domaine d’application dans lequel le thread est en cours d’exécution (AppDomain.Unload utilise Thread.Abort pour arrêter des threads), votre thread doit gérer l’exception ThreadAbortException et exécuter tout traitement final dans une clause finally, comme indiqué dans le code suivant.

Try  
    ' Code that is executing when the thread is aborted.  
Catch ex As ThreadAbortException  
    ' Clean-up code can go here.  
    ' If there is no Finally clause, ThreadAbortException is  
    ' re-thrown by the system at the end of the Catch clause.
Finally  
    ' Clean-up code can go here.  
End Try  
' Do not put clean-up code here, because the exception
' is rethrown at the end of the Finally clause.  
try
{  
    // Code that is executing when the thread is aborted.  
}
catch (ThreadAbortException ex)
{  
    // Clean-up code can go here.  
    // If there is no Finally clause, ThreadAbortException is  
    // re-thrown by the system at the end of the Catch clause.
}  
// Do not put clean-up code here, because the exception
// is rethrown at the end of the Finally clause.  

Votre code de nettoyage doit se trouver dans la clause catch ou la clause finally, car une exception ThreadAbortException est de nouveau levée par le système à la fin de la clause finally, ou à la fin de la clause catch s’il n’existe pas de clause finally.

Vous pouvez empêcher le système de lever une nouvelle exception en appelant la méthode Thread.ResetAbort. Vous ne devez néanmoins le faire que si c’est votre propre code qui a provoqué l’exception ThreadAbortException.

Voir aussi