Classe de thread dans Delphi
Raptor[Studio Mental]
http://mental.mentsu.com
troisième
Après avoir parlé du constructeur, regardons le destructeur :
destructeur TThread.Destroy ;
commencer
si (FThreadID <> 0) et non FFinished alors
commencer
Mettre fin;
si FCreateSuspended alors
CV;
Attendre ;
fin;
si FHandle <> 0 alors CloseHandle(FHandle);
hérité Détruire;
FFatalException.Free;
Supprimer le fil ;
fin;
Avant que l'objet thread ne soit libéré, vérifiez d'abord si le thread est toujours en cours d'exécution (l'ID du thread n'est pas 0 et l'indicateur de fin de thread n'est pas défini), le processus Terminate est appelé pour terminer le thread. La procédure Terminate définit simplement l'indicateur Terminé de la classe de thread, comme dans le code suivant :
PROcédure TThread.Terminate ;
commencer
FTerminé := Vrai ;
fin;
Par conséquent, le thread doit continuer à s'exécuter jusqu'à ce qu'il se termine normalement, plutôt que de mettre fin au thread immédiatement.
Une petite digression ici : De nombreuses personnes m'ont demandé comment terminer un fil de discussion "immédiatement" (en faisant bien sûr référence aux fils de discussion créés avec TThread). Bien sûr, ça ne marche pas ! La seule façon de terminer un thread est de laisser la méthode Execute terminer l'exécution. Par conséquent, de manière générale, si vous souhaitez que votre thread se termine le plus rapidement possible, vous devez constamment vérifier l'indicateur Terminé dans la méthode Execute dans un court laps de temps. que vous puissiez sortir à temps. C'est un principe très important lors de la conception de code threadé !
Bien sûr, si vous devez pouvoir quitter le thread "immédiatement", alors la classe TThread n'est pas un bon choix, car si vous utilisez l'API pour terminer le thread de force, l'objet thread TThread ne pourra finalement pas être libéré correctement. , et une violation d'accès se produira lorsque l'objet sera détruit. Dans ce cas, vous ne pouvez utiliser que les fonctions API ou RTL pour créer des threads.
Si le thread est dans l'état de démarrage suspendu, transférez le thread à l'état d'exécution, puis appelez WaitFor pour attendre. Sa fonction est d'attendre la fin du thread avant de continuer à s'exécuter. L'implémentation de WaitFor sera expliquée plus tard.
Une fois le thread terminé, fermez le handle du thread (le handle existe lorsqu'un thread normal est créé) et libérez l'objet thread créé par le système d'exploitation.
Appelez ensuite TObject.Destroy pour libérer cet objet et libérer l'objet d'exception intercepté, et enfin appelez RemoveThread pour réduire le nombre de threads dans le processus.
Les autres aspects concernant les paramètres de suspension/reprise et de priorité des threads ne font pas l'objet de cet article et ne seront pas abordés à nouveau. Ce qui sera discuté ci-dessous, ce sont les deux autres objectifs de cet article : Synchroniser et WaitFor.
Mais avant d'introduire ces deux fonctions, deux autres technologies de synchronisation des threads doivent être introduites : les événements et les sections critiques.
Les événements sont différents des événements dans Delphi. Essentiellement, Event est équivalent à une variable booléenne globale. Il comporte deux opérations d'affectation : Set et Reset, qui équivalent à le définir sur True ou False. Et la vérification de sa valeur se fait via l’opération WaitFor. Correspondant à la plateforme Windows, il existe trois fonctions API : SetEvent, ResetEvent et WaitForSingleObject (il existe plusieurs API qui implémentent la fonction WaitFor, celle-ci est la plus simple).
Ces trois éléments sont des primitives, donc Event peut implémenter des applications multithreads que les variables booléennes générales ne peuvent pas. Les fonctions de Set et Reset ont déjà été mentionnées. Parlons maintenant de la fonction de WaitFor :
La fonction de WaitFor est de vérifier si l'état de l'événement est l'état Set (équivalent à True). Si c'est le cas, il revient immédiatement. Sinon, il attend qu'il passe à l'état Set. le thread appelant WaitFor est dans un état suspendu. De plus, WaitFor a un paramètre pour le réglage du délai d'attente. Si ce paramètre est 0, il n'attend pas et renvoie immédiatement l'état de l'événement. S'il est INFINI, il attend indéfiniment jusqu'à ce que l'état Set se produise. attend le nombre de millisecondes correspondant. Renvoie ensuite l'état de l'événement.
Lorsque l'événement passe de l'état Reset à l'état Set, il réveille les autres threads suspendus en raison de l'événement WaitFor. C'est pourquoi il est appelé Event. Le soi-disant « événement » fait référence à une « transition d'état ». Ces informations de « transition d'état » peuvent être transmises entre les threads via des événements.
Bien entendu, une fonction similaire peut également être obtenue en utilisant une variable booléenne protégée (voir l'introduction de la section critique ci-dessous), à condition que WaitFor soit remplacé par une boucle de code qui vérifie la valeur booléenne. Fonctionnellement, il n'y a aucun problème, mais en utilisation réelle, vous constaterez qu'une telle attente occupera beaucoup de ressources CPU, réduira les performances du système et affectera la vitesse d'exécution des autres threads, ce n'est donc pas économique et parfois même possible. problèmes. Il n’est donc pas recommandé de l’utiliser de cette façon.
(à suivre)