Salut,
J'ai un nouveau probleme :)
Je voudrais recuperer la pile de mon programme.
Pour ca, je suis alle recuperer l'exemple poste par Arnaud Debaene mais
ca ne marche pas...
Donc, je vous poste ici mon code en esperant que vous puissiez m'aider :)
3 fonctions :
MyGetProcAddress : Retourne les adresses des fonctions
SymFunctionTableAccess64 et SymGetModuleBase64 (je pense que mon pb
vient de la, enfin des parametres dans StackWalk)
ManewFonction : fonction appelle lors de CreateThread et qui est cense
recuper la pile
Button4Click : procedure executee lors du Click sur un bouton (il faut
partir de la pour lire le code)
function MyGetProcAddress(NbrFunc: integer): Pointer;
var
Instance: Hwnd;
begin
//Normalement, rien d'anormal dans cette fonction (niveau code)
//Peut etre du point de vue logique (il ne faut pas etre pas les
// chargees ?)
Instance := LoadLibrary('DbgHelp.dll');
if Instance = 0 then
begin
MessageBox(0, 'Impossible de chager la DLL : DbgHelp.dll', 'Erreur
de chargement',
MB_OK or MB_ICONERROR);
Result := nil;
Exit;
end;
if NbrFunc = 1 then
Result := GetProcAddress(Instance, 'SymFunctionTableAccess64')
else Result := GetProcAddress(Instance, 'SymGetModuleBase64');
end;
function ManewFonction(param: Pointer): Boolean;
var
Contexte : CONTEXT;
StackFrame : TSTACKFRAME64;
Liste : TStringList;
Dbg : TDbgDebugger; //Implementation perso de DbgHelp car Borland ne
l'a pas mis !
Cpt: Integer;
MonThr : Cardinal;
begin
Dbg := TDbgDebugger.Create;
Liste := TStringList.Create;
MonThr := Form1.HandleThread; //J'ai essaye avec GetCurrentThread,
ca passe pas non plus.
//Petit PS: j'avais essaye de passer le pointeur de HandleThread par
le Param, mais ca passe pas,
//Savez vous pourquoi ??
//Suspend le thread pour lire
SuspendThread(MonThr);
//Recupere le context
Contexte.ContextFlags := CONTEXT_FULL;
if GetThreadContext(MonThr, Contexte) = False then
begin
//Si je ne fais pas un GetThreadContext sur le GetCurrentThread, je
n'arrive jamais a l'avoir !
MessageBox(0, 'GetThreadContext echoue', 'Erreur', Mb_OK or
Mb_ICONERROR);
MessageBox(0, PChar(SysErrorMessage(GetLastError())), 'Erreur',
Mb_OK or Mb_ICONERROR); //Donne le message d'erreur en clair
end;
//Remplit de 0 la structure
FillChar(StackFrame, SizeOf(TSTACKFRAME64), #0);
// Initilaise le context pour la 1ere fois (special x86)
StackFrame.AddrPC.Offset := Contexte.Eip;
StackFrame.AddrPC.Mode := AddrModeFlat;
StackFrame.AddrStack.Offset := Contexte.Esp;
StackFrame.AddrStack.Mode := AddrModeFlat;
StackFrame.AddrFrame.Offset := Contexte.Ebp;
StackFrame.AddrFrame.Mode := AddrModeFlat;
//Creer un Compteur pour voir le nombre de lignes sur la pile
Cpt :=0;
//Boucle pour recupere la pile
//Je pense donc que le pb vient des
// - PFunctionTableAccessProc64(MyGetProcAddress(1)) - Pointe vers la
// fonction de DbgHelp
// - PGetModuleBaseProc64(MyGetProcAddress(2)) ->Pointe vers la
// fonction de DbgHelp
While Dbg.StackWalk64(IMAGE_FILE_MACHINE_I386, GetCurrentProcess, MonThr,
@StackFrame, @Contexte, nil,
PFunctionTableAccessProc64(MyGetProcAddress(1)),
PGetModuleBaseProc64(MyGetProcAddress(2)), nil) = True do
begin
Liste.Add('Offset : ' + IntToHex(StackFrame.AddrPC.Offset, 8));
Inc(Cpt);
//if Cpt >= 10000 then Break; //Si je ne met pas ca, je suis dans
une boucle infinie !
if StackFrame.AddrPC.Offset = 0 then Break;
end;
//Sauvegarde le fichier
Liste.Add(IntToStr(Cpt));
Liste.Add('Fini stackWalk');
Liste.SaveToFile('C:\Stack.txt');
Result := True; //J'en vois pas l'interet mais ils renvoient tous
True pour cette fonction
//sur les exmples vus
//Voir le resultat sur ma fiche de delphi
Form1.ListBox1.Items := Liste;
//Destruction des objets utilises
Dbg.Free;
Liste.Free;
end;
procedure TForm1.Button4Click(Sender: TObject);
var
HandleEvent, Newthread : Hwnd;
begin
//J'ai essaye de traduire le code de Arnaud Debaene et il avait
utilise un Event avec le WaitForSingleObject
HandleEvent := CreateEvent(nil, False, False, nil);
if Handleevent = 0 then
begin
MessageBox(0, 'Handle 0 pour Event', 'Erreur', Mb_OK or Mb_ICONERROR);
Exit;
end;
if DuplicateHandle(GetCurrentProcess, GetCurrentThread,
GetCurrentProcess, @HandleThread,
0, False, DUPLICATE_SAME_ACCESS) = False then
begin
MessageBox(0, 'DuplicateHandle non reussi', 'Erreur', Mb_OK or
Mb_ICONERROR);
Exit;
end;
NewThread := CreateThread(nil, 0, @MaNewFonction, nil, 0, thread_id);
if NewThread = 0 then
begin
MessageBox(0, 'Handle 0 pour NewThread', 'Erreur', Mb_OK or
Mb_ICONERROR);
Exit;
end;
//WaitForSingleObject(HandleEvent, INFINITE); //Mis en commentaire
car me fais faire une boucle infinie
//A moins que sauver la pile ne prenne plus d'une minute ?!
CloseHandle(NewThread);
CloseHandle(HandleThread);
end;
Il faut partir du Button4Click :)
Je sais que le nom des fonctions n'est pas tres explicites mais je suis
en train de tester, alors bon...j'ai pas encore de mise en forme
J'ai essaye de detailler les differents problemes au fur et a mesure
dans les commentaires, si vous ne comprenez pas quelque chose, n'hesitez
pas a me demander.
PS : si vous voulez voir mon implementation de DbgHelp (au cas ou vous
ne detectez pas de grosse erreur) : glayag.free.fr/H_DbgHelp.pas
> Et le thread auxiliaire, il fait quoi? Il n'y a pas un seul appel > bloquant dedans! >
Le thread auxiliaire essaye (enfin j'espere :P)
Ca ne sert à rien d'espérer en programmation!! Si tu mets des traces dans MaNewFoncion ou si tu fais du pas à pas sous ton debugger, ca donne quoi?
<snip>
Ben, HandleThread est une variable (de moi meme pour stocker le
Handle
du Thread dupliqué) de l'objet Form1. Et Form1 est une instance de
la
fiche Windows.
Form1 est une variable globale? Beurk!
Mais qu'est ce que tu entends par : pas la meme signature ?? Ca expliquerait pourquoi mon param de ManewFonction ne passe pas....
La signature de la fonction attendue par CreateThread est (en C) : DWORD WINAPI ThreadProc(LPVOID param)
Assez loin de ce que tu lui passes : function ManewFonction(param: Pointer): Boolean
Je ne sais pas quelle est la convention d'appel par défaut de Delphi, ni si il est capable de faire certaines conversions, donc je ne peux pas t'aider. Mais pour commencer, est ce que tu es sûr qu'on peut lancer un thread en Delphi en lui passant une fonction avec cette signature? Sinon, il y a peut être dans le langage ou la librairie Delphi un moyen "standard" de gérer les threads.
Arnaud
yarocco wrote:
> Et le thread auxiliaire, il fait quoi? Il n'y a pas un seul appel
> bloquant dedans!
>
Le thread auxiliaire essaye (enfin j'espere :P)
Ca ne sert à rien d'espérer en programmation!! Si tu mets des traces
dans MaNewFoncion ou si tu fais du pas à pas sous ton debugger, ca
donne quoi?
<snip>
Ben, HandleThread est une variable (de moi meme pour stocker le
Handle
du Thread dupliqué) de l'objet Form1. Et Form1 est une instance de
la
fiche Windows.
Form1 est une variable globale? Beurk!
Mais qu'est ce que tu entends par : pas la meme signature ??
Ca expliquerait pourquoi mon param de ManewFonction ne passe pas....
La signature de la fonction attendue par CreateThread est (en C) :
DWORD WINAPI ThreadProc(LPVOID param)
Assez loin de ce que tu lui passes :
function ManewFonction(param: Pointer): Boolean
Je ne sais pas quelle est la convention d'appel par défaut de Delphi,
ni si il est capable de faire certaines conversions, donc je ne peux
pas t'aider. Mais pour commencer, est ce que tu es sûr qu'on peut
lancer un thread en Delphi en lui passant une fonction avec cette
signature? Sinon, il y a peut être dans le langage ou la librairie
Delphi un moyen "standard" de gérer les threads.
> Et le thread auxiliaire, il fait quoi? Il n'y a pas un seul appel > bloquant dedans! >
Le thread auxiliaire essaye (enfin j'espere :P)
Ca ne sert à rien d'espérer en programmation!! Si tu mets des traces dans MaNewFoncion ou si tu fais du pas à pas sous ton debugger, ca donne quoi?
<snip>
Ben, HandleThread est une variable (de moi meme pour stocker le
Handle
du Thread dupliqué) de l'objet Form1. Et Form1 est une instance de
la
fiche Windows.
Form1 est une variable globale? Beurk!
Mais qu'est ce que tu entends par : pas la meme signature ?? Ca expliquerait pourquoi mon param de ManewFonction ne passe pas....
La signature de la fonction attendue par CreateThread est (en C) : DWORD WINAPI ThreadProc(LPVOID param)
Assez loin de ce que tu lui passes : function ManewFonction(param: Pointer): Boolean
Je ne sais pas quelle est la convention d'appel par défaut de Delphi, ni si il est capable de faire certaines conversions, donc je ne peux pas t'aider. Mais pour commencer, est ce que tu es sûr qu'on peut lancer un thread en Delphi en lui passant une fonction avec cette signature? Sinon, il y a peut être dans le langage ou la librairie Delphi un moyen "standard" de gérer les threads.
Arnaud
yarocco
> Ca ne sert à rien d'espérer en programmation!! Si tu mets des traces dans MaNewFoncion ou si tu fais du pas à pas sous ton debugger, ca donne quoi?
OK... c'etait une facon de parler. ManewFonction a pour but de recuperer la CallStack mais ne le fait pas sinon je n'ecrirais pas ici ! Elle en recupere 1 et puis ne met que des 00000012 (en boucle infinie puisque le break est fait par un False de StackWalk ou StackFrame.AddrPC.Offset = 0) Ma fonction est bien appelle, a l'air de marcher jusqu'au StackWalk
> Form1 est une variable globale? Beurk!
Oui, variable globale, mais c'est ainsi que Delphi gere les forms (fiche de windows) en standard...
La signature de la fonction attendue par CreateThread est (en C) : DWORD WINAPI ThreadProc(LPVOID param)
Assez loin de ce que tu lui passes : function ManewFonction(param: Pointer): Boolean
Mis a part le Boolean au lieu du DWORD pour le retour (qui n'est pas utilise), je ne vois pas de difference. Le LPVOIR equivaut a un simple pointeur sur n'importe quel type. Apres, pour la traduction du WINAPI, je ne sais pas ce que ca signifie.
Je ne sais pas quelle est la convention d'appel par défaut de Delphi, ni si il est capable de faire certaines conversions, donc je ne peux pas t'aider. Mais pour commencer, est ce que tu es sûr qu'on peut lancer un thread en Delphi en lui passant une fonction avec cette signature? Sinon, il y a peut être dans le langage ou la librairie Delphi un moyen "standard" de gérer les threads.
Arnaud
Je vais etudier ce cote, je viens de decouvrir qu'il y avait un gestion interne (enfin, avec des objets de Borland) des Threads
> Ca ne sert à rien d'espérer en programmation!! Si tu mets des traces
dans MaNewFoncion ou si tu fais du pas à pas sous ton debugger, ca
donne quoi?
OK... c'etait une facon de parler.
ManewFonction a pour but de recuperer la CallStack mais ne le fait pas
sinon je n'ecrirais pas ici ! Elle en recupere 1 et puis ne met que des
00000012 (en boucle infinie puisque le break est fait par un False de
StackWalk ou StackFrame.AddrPC.Offset = 0)
Ma fonction est bien appelle, a l'air de marcher jusqu'au StackWalk
> Form1 est une variable globale? Beurk!
Oui, variable globale, mais c'est ainsi que Delphi gere les forms (fiche
de windows) en standard...
La signature de la fonction attendue par CreateThread est (en C) :
DWORD WINAPI ThreadProc(LPVOID param)
Assez loin de ce que tu lui passes :
function ManewFonction(param: Pointer): Boolean
Mis a part le Boolean au lieu du DWORD pour le retour (qui n'est pas
utilise), je ne vois pas de difference.
Le LPVOIR equivaut a un simple pointeur sur n'importe quel type.
Apres, pour la traduction du WINAPI, je ne sais pas ce que ca signifie.
Je ne sais pas quelle est la convention d'appel par défaut de Delphi,
ni si il est capable de faire certaines conversions, donc je ne peux
pas t'aider. Mais pour commencer, est ce que tu es sûr qu'on peut
lancer un thread en Delphi en lui passant une fonction avec cette
signature? Sinon, il y a peut être dans le langage ou la librairie
Delphi un moyen "standard" de gérer les threads.
Arnaud
Je vais etudier ce cote, je viens de decouvrir qu'il y avait un gestion
interne (enfin, avec des objets de Borland) des Threads
> Ca ne sert à rien d'espérer en programmation!! Si tu mets des traces dans MaNewFoncion ou si tu fais du pas à pas sous ton debugger, ca donne quoi?
OK... c'etait une facon de parler. ManewFonction a pour but de recuperer la CallStack mais ne le fait pas sinon je n'ecrirais pas ici ! Elle en recupere 1 et puis ne met que des 00000012 (en boucle infinie puisque le break est fait par un False de StackWalk ou StackFrame.AddrPC.Offset = 0) Ma fonction est bien appelle, a l'air de marcher jusqu'au StackWalk
> Form1 est une variable globale? Beurk!
Oui, variable globale, mais c'est ainsi que Delphi gere les forms (fiche de windows) en standard...
La signature de la fonction attendue par CreateThread est (en C) : DWORD WINAPI ThreadProc(LPVOID param)
Assez loin de ce que tu lui passes : function ManewFonction(param: Pointer): Boolean
Mis a part le Boolean au lieu du DWORD pour le retour (qui n'est pas utilise), je ne vois pas de difference. Le LPVOIR equivaut a un simple pointeur sur n'importe quel type. Apres, pour la traduction du WINAPI, je ne sais pas ce que ca signifie.
Je ne sais pas quelle est la convention d'appel par défaut de Delphi, ni si il est capable de faire certaines conversions, donc je ne peux pas t'aider. Mais pour commencer, est ce que tu es sûr qu'on peut lancer un thread en Delphi en lui passant une fonction avec cette signature? Sinon, il y a peut être dans le langage ou la librairie Delphi un moyen "standard" de gérer les threads.
Arnaud
Je vais etudier ce cote, je viens de decouvrir qu'il y avait un gestion interne (enfin, avec des objets de Borland) des Threads
yarocco
Bon, je viens de refaire le tout avec les Threads a la Delphi et j'ai bien des resultats. C'etait mon implementation qui etait pas bonne !! J'ai une cinquantaine d'addresses, alors est ce que c'est bon ?? ou il y en a plus ?
Merci encore
Bon, je viens de refaire le tout avec les Threads a la Delphi et j'ai
bien des resultats.
C'etait mon implementation qui etait pas bonne !!
J'ai une cinquantaine d'addresses, alors est ce que c'est bon ?? ou il y
en a plus ?
Bon, je viens de refaire le tout avec les Threads a la Delphi et j'ai bien des resultats. C'etait mon implementation qui etait pas bonne !! J'ai une cinquantaine d'addresses, alors est ce que c'est bon ?? ou il y en a plus ?
Merci encore
Arnaud Debaene
yarocco wrote:
Bon, je viens de refaire le tout avec les Threads a la Delphi et j'ai bien des resultats. C'etait mon implementation qui etait pas bonne !!
Je me disais aussi... J'imagine que ton utilisation de CreateThread devait foutre en l'air la pile d'appel de ton thread secondaire, ou quelque chose du genre.
J'ai une cinquantaine d'addresses, alors est ce que c'est bon ?? ou il y en a plus ?
Est ce que ca commence par BaseProcessStart dans kernel32 (visible uniquement si tu as les symboles de kernel32), suivi probablement d'un paquet de routines d'initisialisation de Delphi, du main de Delphi (ou ce qui en tient lieu), et se termine par TForm1.Button4Click (puis quelques appels pour WaitForSingleObject) ? Si c'est çà, alors c'est bon.
Arnaud
yarocco wrote:
Bon, je viens de refaire le tout avec les Threads a la Delphi et j'ai
bien des resultats.
C'etait mon implementation qui etait pas bonne !!
Je me disais aussi... J'imagine que ton utilisation de CreateThread devait
foutre en l'air la pile d'appel de ton thread secondaire, ou quelque chose
du genre.
J'ai une cinquantaine d'addresses, alors est ce que c'est bon ?? ou
il y en a plus ?
Est ce que ca commence par BaseProcessStart dans kernel32 (visible
uniquement si tu as les symboles de kernel32), suivi probablement d'un
paquet de routines d'initisialisation de Delphi, du main de Delphi (ou ce
qui en tient lieu), et se termine par TForm1.Button4Click (puis quelques
appels pour WaitForSingleObject) ? Si c'est çà, alors c'est bon.
Bon, je viens de refaire le tout avec les Threads a la Delphi et j'ai bien des resultats. C'etait mon implementation qui etait pas bonne !!
Je me disais aussi... J'imagine que ton utilisation de CreateThread devait foutre en l'air la pile d'appel de ton thread secondaire, ou quelque chose du genre.
J'ai une cinquantaine d'addresses, alors est ce que c'est bon ?? ou il y en a plus ?
Est ce que ca commence par BaseProcessStart dans kernel32 (visible uniquement si tu as les symboles de kernel32), suivi probablement d'un paquet de routines d'initisialisation de Delphi, du main de Delphi (ou ce qui en tient lieu), et se termine par TForm1.Button4Click (puis quelques appels pour WaitForSingleObject) ? Si c'est çà, alors c'est bon.
Arnaud
yarocco
> Est ce que ca commence par BaseProcessStart dans kernel32 (visible uniquement si tu as les symboles de kernel32), suivi probablement d'un paquet de routines d'initisialisation de Delphi, du main de Delphi (ou ce qui en tient lieu), et se termine par TForm1.Button4Click (puis quelques appels pour WaitForSingleObject) ? Si c'est çà, alors c'est bon.
Arnaud
j'suis passer par un Sleep(5000) pour l'analyse de la CallStack, ca marche aussi bien que le WaitForSingleObject que je n'arrivais pas a terminer :)
> Est ce que ca commence par BaseProcessStart dans kernel32 (visible
uniquement si tu as les symboles de kernel32), suivi probablement d'un
paquet de routines d'initisialisation de Delphi, du main de Delphi (ou ce
qui en tient lieu), et se termine par TForm1.Button4Click (puis quelques
appels pour WaitForSingleObject) ? Si c'est çà, alors c'est bon.
Arnaud
j'suis passer par un Sleep(5000) pour l'analyse de la CallStack, ca
marche aussi bien que le WaitForSingleObject que je n'arrivais pas a
terminer :)
> Est ce que ca commence par BaseProcessStart dans kernel32 (visible uniquement si tu as les symboles de kernel32), suivi probablement d'un paquet de routines d'initisialisation de Delphi, du main de Delphi (ou ce qui en tient lieu), et se termine par TForm1.Button4Click (puis quelques appels pour WaitForSingleObject) ? Si c'est çà, alors c'est bon.
Arnaud
j'suis passer par un Sleep(5000) pour l'analyse de la CallStack, ca marche aussi bien que le WaitForSingleObject que je n'arrivais pas a terminer :)
Arnaud Debaene
yarocco wrote:
j'suis passer par un Sleep(5000) pour l'analyse de la CallStack, ca marche aussi bien que le WaitForSingleObject que je n'arrivais pas a terminer :)
Non! C'est de la programmation à la petite semaine! Ça marche jusqu'à ce que ton système soit suffisamment chargé pour que le démarrage du thread auxiliaire prenne plus de 5s. Même si c'est peu probable, pourquoi faire intervenir un élément non déterministe et de "chance" alors que la solution avec un event fonctionne parfaitement, du moins si tu le fais correctement?
Je viens de relire ton code, qui est faux par rapport à la gestion de cet Event.: - HandleEvent doit être une variable de TForm1, pas une variable locale de TForm1.Button4Click. Il doit en effet être accessible depuis ManewFonction - HandleEvent est un HANDLE, pas un HWND. - A la fin de ManewFonction, il faut lever l'Event en question, pour permettre au thread principal de continuer : SetEvent(Form1.HandleEvent).
C'est sûr que si tu fais un WaitForSingleObject sur l'Event et ne lève jamais cet événement, ton thread principal va rester bloqué...
Arnaud
yarocco wrote:
j'suis passer par un Sleep(5000) pour l'analyse de la CallStack, ca
marche aussi bien que le WaitForSingleObject que je n'arrivais pas a
terminer :)
Non! C'est de la programmation à la petite semaine! Ça marche jusqu'à ce que
ton système soit suffisamment chargé pour que le démarrage du thread
auxiliaire prenne plus de 5s.
Même si c'est peu probable, pourquoi faire intervenir un élément non
déterministe et de "chance" alors que la solution avec un event fonctionne
parfaitement, du moins si tu le fais correctement?
Je viens de relire ton code, qui est faux par rapport à la gestion de cet
Event.:
- HandleEvent doit être une variable de TForm1, pas une variable locale de
TForm1.Button4Click. Il doit en effet être accessible depuis ManewFonction
- HandleEvent est un HANDLE, pas un HWND.
- A la fin de ManewFonction, il faut lever l'Event en question, pour
permettre au thread principal de continuer : SetEvent(Form1.HandleEvent).
C'est sûr que si tu fais un WaitForSingleObject sur l'Event et ne lève
jamais cet événement, ton thread principal va rester bloqué...
j'suis passer par un Sleep(5000) pour l'analyse de la CallStack, ca marche aussi bien que le WaitForSingleObject que je n'arrivais pas a terminer :)
Non! C'est de la programmation à la petite semaine! Ça marche jusqu'à ce que ton système soit suffisamment chargé pour que le démarrage du thread auxiliaire prenne plus de 5s. Même si c'est peu probable, pourquoi faire intervenir un élément non déterministe et de "chance" alors que la solution avec un event fonctionne parfaitement, du moins si tu le fais correctement?
Je viens de relire ton code, qui est faux par rapport à la gestion de cet Event.: - HandleEvent doit être une variable de TForm1, pas une variable locale de TForm1.Button4Click. Il doit en effet être accessible depuis ManewFonction - HandleEvent est un HANDLE, pas un HWND. - A la fin de ManewFonction, il faut lever l'Event en question, pour permettre au thread principal de continuer : SetEvent(Form1.HandleEvent).
C'est sûr que si tu fais un WaitForSingleObject sur l'Event et ne lève jamais cet événement, ton thread principal va rester bloqué...
Arnaud
yarocco
> Non! C'est de la programmation à la petite semaine! Ça marche jusqu'à ce que ton système soit suffisamment chargé pour que le démarrage du thread auxiliaire prenne plus de 5s. Même si c'est peu probable, pourquoi faire intervenir un élément non déterministe et de "chance" alors que la solution avec un event fonctionne parfaitement, du moins si tu le fais correctement?
Je viens de relire ton code, qui est faux par rapport à la gestion de cet Event.: - HandleEvent doit être une variable de TForm1, pas une variable locale de TForm1.Button4Click. Il doit en effet être accessible depuis ManewFonction - HandleEvent est un HANDLE, pas un HWND. - A la fin de ManewFonction, il faut lever l'Event en question, pour permettre au thread principal de continuer : SetEvent(Form1.HandleEvent).
C'est sûr que si tu fais un WaitForSingleObject sur l'Event et ne lève jamais cet événement, ton thread principal va rester bloqué...
Arnaud
Alors la, je te remercie bcp. Je n'avais vu que le ResumeThread sur ton code...:( Je n'ai jamais travaille avec WaitForSingleObject, donc je ne savais pas comment il fonctionnait.
> Non! C'est de la programmation à la petite semaine! Ça marche jusqu'à ce que
ton système soit suffisamment chargé pour que le démarrage du thread
auxiliaire prenne plus de 5s.
Même si c'est peu probable, pourquoi faire intervenir un élément non
déterministe et de "chance" alors que la solution avec un event fonctionne
parfaitement, du moins si tu le fais correctement?
Je viens de relire ton code, qui est faux par rapport à la gestion de cet
Event.:
- HandleEvent doit être une variable de TForm1, pas une variable locale de
TForm1.Button4Click. Il doit en effet être accessible depuis ManewFonction
- HandleEvent est un HANDLE, pas un HWND.
- A la fin de ManewFonction, il faut lever l'Event en question, pour
permettre au thread principal de continuer : SetEvent(Form1.HandleEvent).
C'est sûr que si tu fais un WaitForSingleObject sur l'Event et ne lève
jamais cet événement, ton thread principal va rester bloqué...
Arnaud
Alors la, je te remercie bcp.
Je n'avais vu que le ResumeThread sur ton code...:(
Je n'ai jamais travaille avec WaitForSingleObject, donc je ne savais pas
comment il fonctionnait.
> Non! C'est de la programmation à la petite semaine! Ça marche jusqu'à ce que ton système soit suffisamment chargé pour que le démarrage du thread auxiliaire prenne plus de 5s. Même si c'est peu probable, pourquoi faire intervenir un élément non déterministe et de "chance" alors que la solution avec un event fonctionne parfaitement, du moins si tu le fais correctement?
Je viens de relire ton code, qui est faux par rapport à la gestion de cet Event.: - HandleEvent doit être une variable de TForm1, pas une variable locale de TForm1.Button4Click. Il doit en effet être accessible depuis ManewFonction - HandleEvent est un HANDLE, pas un HWND. - A la fin de ManewFonction, il faut lever l'Event en question, pour permettre au thread principal de continuer : SetEvent(Form1.HandleEvent).
C'est sûr que si tu fais un WaitForSingleObject sur l'Event et ne lève jamais cet événement, ton thread principal va rester bloqué...
Arnaud
Alors la, je te remercie bcp. Je n'avais vu que le ResumeThread sur ton code...:( Je n'ai jamais travaille avec WaitForSingleObject, donc je ne savais pas comment il fonctionnait.
adebaene
yarocco wrote:
Je n'ai jamais travaille avec WaitForSingleObject, donc je ne savais
pas
comment il fonctionnait.
Dans ce cas on lit la doc...
Arnaud
yarocco wrote:
Je n'ai jamais travaille avec WaitForSingleObject, donc je ne savais