Attendre la fin d'un thread créé par CreateThread()

Attendre la fin d'un thread créé par CreateThread() - Delphi/Pascal - Programmation

Marsh Posté le 08-09-2005 à 17:23:51    

Yop, voilà ce que j'ai codé à ce jour :
 

Code :
  1. function TMaClasse.LancerProcessus: boolean;
  2. begin
  3.     temps.TempsDebut := now;
  4.     FfrmProcessing := TfrmProcessing.Create(nil);
  5.     FfrmProcessing.Show;
  6.     monThread.Th := CreateThread(nil, 0, @LeProcess, self, 0, monThread.Tid);
  7.     WaitForSingleObject(monThread.Th, INFINITE);
  8.     MessageBox(processHandle, 'fini', 'yes', 0);
  9.     Result := true;
  10. end;


 
Ensuite, dans LeProcess, j'appelle régulièrement une méthode MAJInformation(), laquelle mets à jour les informations concernant l'état d'avancement du processus dans la fenêtre FfrmProcessing. Cependant, lors de la première exécution de cette méthode, tout se bloque dès que je modifie une propriété d'un composant de la fenêtre créée :'(
 
Voilà un extrait de MAJInformation :

Code :
  1. procedure TMaClasse.MAJInformation;
  2. begin
  3.     with FfrmProcessing do
  4.         begin
  5.                bar1.position := (EffectueGlobal * 100) div TotalGlobal;
  6.                lblPourcentage.Caption := IntToStr(bar1.Position) + '%';
  7.                bar2.position := (EffectueCourant * 100) div TotalCourant;
  8.         end;
  9. end;


Quand la méthode est appelée dans LeProcess, tout se bloque à la ligne 5 de MAJInformation.
 
Cependant, tout fonctionne bien lorsque je n'utilise pas WaitForSingleObject mais dans ce cas, je ne sais pas comment savoir si ma fonction s'est terminée avec succès pour revenir enfin sur ma fiche principale.
 
Savez-vous à quoi est due cette erreur ?
 
Merci à vous :)


Message édité par Inekman le 08-09-2005 à 18:06:00
Reply

Marsh Posté le 08-09-2005 à 17:23:51   

Reply

Marsh Posté le 09-09-2005 à 00:47:45    

Bon finalement j'ai trouvé une solution qui fonctionne mais par contre je sais pas si "c'est bien" de faire comme ça ^^ :
 

Code :
  1. LancerProcessus;
  2. repeat
  3.        Application.HandleMessage;
  4. until isThreadTerminated;


isThreadTerminated est un booleen initialisé à False au lancement de LancerProcessus et à la fin de l'exécution du thread, je passe cette variable à True. Et donc dès que c'est fini, ben je sors de la boucle et j'peux revenir à la fenêtre principale du programme.  
 
J'ai testé Application.ProcessMessage et HandleMessage, sans trop savoir qui fait quoi, et il s'avère que le 1er utilise 100 % du proc alors qu'avec HandleMessage c'est bon.
 
 
Maintenant j'ai un autre problème :D
 
Pendant l'exécution de la fonction du thread, lorsqu'on arrive à cette ligne :
 

NomCourt := Copy(Reglage.Source_chemin + Reglage.Source_fichier, 0, Length(Reglage.Source_chemin + Reglage.Source_fichier) - 8);


J'ai le message d'erreur suivant qui s'affiche :'( :

---------------------------
Debugger Exception Notification
---------------------------
Project Project1.exe raised exception class EOutOfMemory with message 'Out of memory'. Process stopped. Use Step or Run to continue.
---------------------------
OK   Help    
---------------------------


 
Et je ne sais pas quoi changer/corriger pour éviter ce bug [:airforceone]  
 
Qu'est-ce qui ne va pas ? :ange:

Reply

Marsh Posté le 09-09-2005 à 09:56:36    

Il fait quoi ton thread ? Si c'est copier un fichier, t'as une boite toute faite qui existe (celle utilisée par Windows, voir SHFileOperation).


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
Reply

Marsh Posté le 09-09-2005 à 12:39:17    

Non non il ne copie pas de fichier, mais il fait un traitement dessus. Il récupère des données et les placent dans un autre fichier.

Reply

Marsh Posté le 09-09-2005 à 16:48:03    

Ta methode pour attendre la fin du thread me parait parfaite  
HandleMessage rend la main à l'application et revient sur ton code après qu'un message ai été traité. Ca peut attendre indéfiniment si ton programme n'a aucune raison de générer un message, mais autant que je sache, la fin d'un thread(à la sorite de la methode TThtread.Execute pour etre exact) en gènère un, donc pas de problème (Si j'ai dit une bêtise, puissent les Maîtres de ce forum me coriger).
 
Quant à ton exception, mystère. Je suppose que tu a essayé de décomposer (mettre (Reglage.Source_chemin + Reglage.Source_fichier)  dans une string avant la copy). Dans ce cas, ou cela plante-t-il?
 
Autre problème: Ton programme principale ne lance-t-il qu'un thread à la fois et ce thread ne lance-t-ils aucun thread à son tour? Because tu comprendra que quand 2 threads tentent d'acceder aux mème variables en mème temps, les choses se compliquent (c'est peu dire).


Message édité par Zozol le 09-09-2005 à 16:58:56
Reply

Marsh Posté le 09-09-2005 à 18:33:43    

Merci beaucoup pour ta participation zozol.
 
En ce qui concerne l'arrêt du thread, c'est la seule solution que j'ai trouvé. Sache que je n'utilise pas TThread pour mon objet. J'ai tout fait à l'aide de l'api Win32 (apprentissage inside). Normalement il faut utiliser WaitForSingleObject en lui donnant un timeout et elle renvoi un double mot à partir duquel on peut savoir si oui ou non le thread s'est arrêté etc mais chez moi cela bloque complètement le programme. Bref :)
 
Bon concernant le bug, j'ai trouvé finalement ^^. L'erreur venait au moment du lancement du thread auquel je transmet un pointeur comme paramètre. Sauf que là j'ai donné l'adresse du pointeur. Ceci explique cela. [:arg]
 
Bon ben tout marche pour le mieux pour l'instant. Je me demandais juste si la boucle avec le HandleMessage était bien, apparement oui ^^
 
Merci à tous ;)

Reply

Marsh Posté le 16-10-2005 à 01:49:46    

Je reviens à l'attaque à propos de ma fameuse boucle car ayant changé quelque peu mon code, cette astuce ne fonctionne plus :'(
 
La différence réside dans le fait que lorsque j'ai posté cette astuce à l'époque, la fenêtre TfrmProcessing était instanciée dans l'unité de ma fenêtre principale. Or depuis, j'ai décidé de créer cette fenêtre dynamiquement comme ça :
 
frmProcessing := TfrmProcessing.Create(nil);
frmProcessing.Show;
 
A la fin de l'exécution du thread, une méthode de la classe qui a créé cette fenêtre est exécutée :
 
CloseHandle(monThread.Th); // ferme le handle du thread
 
frmProcessing.Timer1.Enabled := false; // au cas où...
frmProcessing.Close; // j'utilisais .Release également
 
ThreadTerminated := true; // la fameuse variable qui est testée dans la boucle citée qq post plus haut
 
Ce qui est bizarre donc, c'est que le thread s'arrête, la fenêtre TfrmProcessing disparaît mais la fenêtre principale ne revient pas, aucun message ne semble lui être envoyé.
 
Je ne sais pas quoi faire :(

Reply

Marsh Posté le 17-10-2005 à 09:33:45    


pd l'exec du thread, les traitements qui se font via la vcl (affichage, etc) doivent se faire via la methode synchonize du thread...

Reply

Marsh Posté le 17-10-2005 à 11:55:54    

To Copy il devrait commencer à 1 plutôt qu'à 0, non ?
 
 

Inekman a écrit :


 
Ce qui est bizarre donc, c'est que le thread s'arrête, la fenêtre TfrmProcessing disparaît mais la fenêtre principale ne revient pas, aucun message ne semble lui être envoyé.


 
Et cette fenêtre principale, tu la caches avant de démarrer le thread ? Tu veux dire quoi par "ne revient pas" ?


---------------
mes programmes ·· les voitures dans les films ·· apprenez à écrire
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed