Une manière appropriée de détruire un objet TThread
Cette question peut sembler triviale, mais j'espère que vous ne l'ignorez pas.
Avant de détruire un TThread objet, il est généralement nécessaire d'attendre jusqu'à ce que le thread qui a appelé la TThread.Méthode Execute() de finitions, car alors seulement pouvons-nous être sûr que, par exemple, les objets détruits à l'intérieur de la classe destructeur ne sont plus accessibles. Par conséquent, il est nécessaire de faire appel à mettre fin à l'ensemble de la Résiliation du pavillon que le fil est de vérifier pour savoir si à la sortie ou pas, et ensuite appeler la WaitFor ().
Parce que le fil peut être suspendu, je pense qu'il est bon de le reprendre avant d'appeler WaitFor, car sinon, le thread appelant serait dans l'impasse. Et parce que le fil peut être suspendu à plusieurs reprises, il doit être repris le même nombre de fois, non?
while Suspended do
Resume;
Si le thread a été créé en suspension, nous n'avons pas à craindre que le TThread.La méthode Execute() sera appelée lorsque nous reprendre le fil uniquement pour y mettre fin, il ne va pas (corrigez-moi si je me trompe).
Ce que j'ai énoncé suggère d'utiliser les lignes de code suivantes pour chaque TThread objet d'être libéré:
MyThread.Terminate;
while MyThread.Suspended do
MyThread.Resume;
MyThread.WaitFor;
MyThread.Free;
Malheureusement, lorsque nous détruisons notre application qui a créé plusieurs threads, l'écriture d'un morceau de code pour chaque TThread objet détruit inutilement rend le code très long et peut-être même opaque.
Donc je suis venu à la conclusion que tous ces pourrait être mis à l'intérieur d'un écrasé le destructeur de la classe TThread grâce à laquelle il suffirait d'appeler le MyThread.Gratuit (ou MyThread.Fin si MyThread.FreeOnTerminate est réglé) sans se soucier de savoir si l'objet détruit est un TThread objet ou pas:
destructor TMyThread.Destroy;
begin
//if FreeOnTerminate, the calling thread cannot wait for itself
if GetCurrentThreadId <> ThreadId then
begin
Terminate;
while Suspended do
Resume;
WaitFor;
end;
{free all objects created in this class}
inherited Destroy;
end;
Pardonnez-moi de poser cette question fondamentale. Je tiens, cependant, à obtenir de connaître votre avis sur cette façon - je l'espère, un moyen universel de détruire TThread objets. Je pose cette questions car je appris de mes collègues de travail sur les codes habituellement utilisés le premier exemple de code pour détruire ces objets, mais ils n'ont jamais utilisé pour vérifier si les fils étant attendu n'ont pas été suspendu que je considérais un peu dangereux si les threads peut être suspendu quelque part dans le code. Donc j'ai essayé de trouver un moyen universel de détruire les objets de cette classe qui permettrait de rendre le code plus clair et plus sûr. J'espère que je n'ai pas faire pire - qu'en pensez-vous?
Merci pour vos suggestions à l'avance.
source d'informationauteur Mariusz Schimke
Vous devez vous connecter pour publier un commentaire.
Beaucoup de ce que votre suggère, c'est déjà réalisés dans le TThread.Détruire le destructeur, et en invoquant TMyThread.gratuit vont faire exactement ce que votre suggérant. Pour le nettoyage de toute des objets appartenant à la classe thread, vous pouvez effectuer que dans le OnTerminate événement, qui sera invoquée dans le cadre de l'arrêt thread logique.
Il n'y a pas de façon universelle pour arrêter un thread, tout comme il n'existe pas de façon universelle (gracieusement) arrêter un processus. Chacun est différent.
Pour certains sujets, il suffit de définir son
Terminated
propriété via leTerminate
méthode. D'autres threads, cependant, les fonctions d'appel commeGetMessage
ouMsgWaitForMultipleObjects
ce qui permet de bloquer jusqu'à ce qu'il se passe quelque chose, comme un message à l'arrivée ou un noyau poignée de devenir signalé.TThread.Terminate
ne peut pas faire l'une de ces choses arriver, donc il ne peut pas faire ces threads arrêter de courir. Lorsque j'ai écrit des fils comme ceux que j'ai fourni mes propres fonctions pour la notification d'entre eux d'arrêter de courir. Je pourrais l'appelerPostThreadMessage
pour forcer un message sur le fil de la file d'attente, ou je pourrais le signal de l'événement que la classe thread a fourni pour la notification d'une demande de résiliation.Ne vous inquiétez pas à propos de la reprise d'une thread suspendue. Vous ne devriez pas être la suspension de toute façon. Le seul moyen sûr de suspendre un fil est le fil de suspendre lui-même, et une fois que vous avez fait cela, vous avez la garantie d'avoir au moins deux threads en contrôle lorsque le thread s'exécute: le fil lui-même à le suspendre, et au moins un autre thread pour le reprendre à nouveau. Un thread doit être en contrôle de sa propre exécution.
Ce serait formidable si
TThread.Terminate
étaient virtuelles. Ensuite, chaque classe thread pourrait fournir de manière personnalisée à informer lui-même qu'il doit s'arrêter. Certains pourriez tout simplementTerminated
et d'autres pourraient s'affichent les messages, les événements de signaux, ou n'importe quoi d'autre dont ils ont besoin. Comme il est, cependant, la non-méthode virtuelle ne fonctionne pas bien avec des fils qui passent beaucoup de leur temps d'attente pour d'autres choses. La façon actuelle ne fonctionne que pour les threads qui sont en mesure de souvent sondage leurTerminated
propriétés.Certains fils ont leur
FreeOnTerminate
définir les propriétés. Pour les threads, votre code n'est pas sûr. Techniquement, il n'est pas sûr d'appel tout méthodes sur les objets depuis le thread pourrait mettre fin à tout moment. Mais même si vous savez que le fil est toujours en cours et le fil objet existe toujours, l'objet va arrêter définitivement existantes, peu de temps après l'appel àTerminate
. Vous ne pouvez pas appelerWaitFor
sur un gratuit-sur-résilier objet thread, et vous avez certainement ne pouvez pas appelerFree
.