2010-09-24 3 views
5

Bonjour À mon formulaire, je crée TFrame à l'exécution. À cette trame, je crée un thread d'arrière-plan avec des commandes exécutées en boucle sans fin. Mais quand je détruis ce cadre, je devrais détruire ce fil. J'essaieCorriger le fil détruire

thread.Suspend; 
thread.Terminate; 
FreeAndNil(thread); 

mais obtenir AV et ThreadError. Comment devrais-je détruire le fil?

+0

double possible de [Libère un TThread automatiquement ou manuellement] (http://stackoverflow.com/questions/3557105/free-a-tthread-either-automatically-or-manually) –

+3

Ne pas suspendre le fil. La méthode terminate définit simplement la propriété Terminated sur true et votre méthode Execute est responsable de terminer le thread. S'il est suspendu, il n'aura pas la chance de se terminer. – jachguate

+0

Un autre problème avec le code ci-dessus, est qu'il libère probablement le thread avant qu'il ait un changement pour terminer la manière normale. –

Répondre

13

Vous devez vous assurer que thread quitte sa méthode d'exécution pour le terminer correctement.

Code pourrait être quelque chose comme ceci:

procedure TThread.Execute; 
begin 
    while not Self.Terminated do 
    begin 
    //do something 
    end; 
end; 

appel quand vous voulez détruire fil:

thread.Terminate; 
thread.WaitFor; 
FreeAndNil(thread); 
+0

Il n'est pas nécessaire d'appeler 'Terminate' et' WaitFor' de l'extérieur, car le destructeur de thread le fera lui-même. Il peut être nécessaire cependant de l'appeler des destructeurs écrasés, avant que tous les champs soient libérés, pour s'assurer que ceux-ci ne sont plus utilisés du fil. – mghie

4

Il suffit de faire thread.Terminate. Mais vous voudrez probablement définir thread.FreeOnTerminate := true lors de sa création.

Bien sûr, dans la boucle étroite de votre thread (c'est-à-dire dans Execute), vous devez vérifier si le thread a été invité à se terminer (vérifiez la propriété Terminated). Si vous trouvez que le thread a été invité à se terminer, il suffit de quitter la boucle et de quitter le Execute.

+0

thread.Terminate définit uniquement la propriété FTerminated sur True. Cela ne détruit pas le fil. – Linas

+2

Je sais. Mais chaque thread doit vérifier cela dans sa méthode Execute.Je suppose que le PO fait cela. –

4

Vous ne devriez jamais appeler suspendre sur un TThread ce ne est pas sûr de le faire et reprendre devrait seulement être utilisé pour démarrer un thread qui a été créé suspendu.

Dans Delphi 2010, la suspension et la reprise, lorsqu'elles ont été dépréciées, et le début de la méthode a été introduit pour renforcer cela.

Pour une explication plus complète, voir ce thread sur les forums Codegears. Après avoir dit qu'il y a 2 façons je vais terminer et libérer un tthread.

1: I Définissez FreeOnTerminate lorsque le thread est créé et que j'appelle simplement.

Thread.Terminate; 

2: Libérer le fil explicitement, comme je l'ai besoin de lire le résultat d'une propriété publique avant que le fil est libéré et après avoir mis fin.

Thread.Terminate; 
Thread.WaitFor; 
//Do somthing like read a public property from thread object 
if Thread <> nil then FreeAndNil(Thread); 

Dans la boucle principale execute, il peut être une bonne idée de mettre un peu de gestion des exceptions. Ou vous pouvez à se demander pourquoi le fil semble mettre fin à son auto. Cela peut provoquer l'AV si le thread est défini sur FreeOnTerminate et qu'il a déjà été libéré lorsque vous essayez de le libérer.

procedure TThread.Execute; 
begin 
    while not Terminated do 
    begin 
    try 
     //do something 
    except 
     on E:Exception do 
     //handle the exception 
    end; 
    end; 
end;