picolo5
Messages postés31Date d'inscriptionlundi 9 août 2004StatutMembreDernière intervention18 décembre 2006
-
10 août 2006 à 15:53
picolo5
Messages postés31Date d'inscriptionlundi 9 août 2004StatutMembreDernière intervention18 décembre 2006
-
31 août 2006 à 13:52
Bonjour à tous !
Je dev un projet qui utlise une dll. Cette dll me permet de me connecter à un serveur et de recuperer une trame.
J ai donc mis en place un thread pour executer l "ecoute" du serveur :
----------------------------------------------------------------------------------------------------------------------------------
unit Unit2;
procedure MonThread.Sync();
begin
Synchronize(Traiter);
End;
procedure MonThread.Execute;
var
test : boolean;
ret : integer;
SPass,SLoggin : string;
begin
while not Terminated do
begin
sleep(1500);
ret := GetMessage(trame);
if ret <> 0 then
begin
// Gerer la reconnection
Init(3002,3001);
CloseSession();
Sleep(5);
SPass := 'EMULOP01';
SLoggin := 'EMULOP01';
OpenSession(PChar(SPass),PChar(SLoggin));
end
else
begin
LaTrame := String(trame);
if LaTrame <> '' then
}
Sync();
//Form1.TraiterTrame(String(Trame)); // Je triche en virant les // et en desactivant Sync(), ca marche mais ce n est
// pas 'securisé'
end;
end;
end;
Je lance mon app (une form avec un bouton pour lancer le thread, la procedure TForm1.TraiterTrame(Trame))
puis je click sur le bouton de lancement du thread :
MyThread:= MonThread.Create(Form1);
Le thread se lance, fait son travail et :
-Si ma souris est sur la form, le synchronize du thread se fait correctement !
-Si ma souris est hors de la form, le thread ne rentre pas ds la procedure à synchronize tant que je ne rentre pas ma souris sur la form. (si je met un point d arret à l entree de Traiter() il n est atteind que ds le cas ou ma souris reviens sur la form !!)
J ai ajouté le passage de la form a mon thread en pensant que le prob venait de la.... mais non :(
J ai essayer de virer tout le code 'superflu' de la methode execute en ne laissant que le synchronize, mais c est idem.
Si je supprime le Sync() et que je le remplace par : Form1.TraiterTrame(String(Trame));
cela marche correctement, mais n est pas 'Sécurisé' ??
cs_Delphiprog
Messages postés4297Date d'inscriptionsamedi 19 janvier 2002StatutMembreDernière intervention 9 janvier 201332 10 août 2006 à 23:35
Salut à tous, amis des threads
A priori, en épurant ton code et en restructurant, voici le code qui fonctionne et qui est aussi proche possible de ce que tu nous décris.
Avant tout, pour éviter les références croisées entre l'unité de la fiche et celle du thread, j'ai ajouté une troisième unité nommée...Unit3 :
unit Unit3;
interface
type
TTrame = array [0..1024] of char;
implementation
end.
Ce qui permettra l'utilisation d'un type commun entre la méthode TraiterTrame de la fiche et le membre de la classe TMonThread (noter l'ajout du 'T' pour respecter les conventions standards).
Voici un extrait du code de la fiche, contenu dans Unit1_1.pas :
var
MonThread: TMonThread = nil;
{ TForm1 }
procedure TForm1.TraiterTrame(Trame: TTrame);
begin
Label1.Caption := Trame;
end ;
procedure TForm1.Button1Click(Sender: TObject);
begin
//pas plus d'1 thread à la fois svp
if MonThread = nilthen
MonThread := TMonthread.Create(Self);
end ;
procedure TForm1.Button2Click(Sender: TObject);
begin
if MonThread <> nilthen
MonThread.Terminate;
MonThread : = nil;
end;
Puis, le meilleur pour la fin :
unit Unit2;
interface
uses
Classes, Windows, Unit1_1, Unit3;
type
TMonThread = class (TThread)
private
FForm: TForm1;
Trame: TTrame;
procedure Fin;
protected
procedure Execute; override;
procedure Traiter;
procedure WhenTerminated(Sender: TObject);
public
constructor Create(Form: TForm1);
end;
implementation
uses SysUtils;
{ TMonThread }
procedure TMonThread.Traiter;
begin
FForm.Ed_Loggin.Text : = 'Test de trame...';
FForm.TraiterTrame(Trame);
end;
constructor TMonThread.Create(Form: TForm1);
begin
inherited Create(False);
FForm := Form;
OnTerminate := WhenTerminated;
FreeOnTerminate := True;
end ;
procedure TMonThread.Execute;
var
ret: integer;
begin
Ret : = 0;
//s'arrêtera automatiquement au bout de 20 secondes
whilenot Terminated and (Ret < 20) do
begin
sleep(1000);
inc(ret);
StrPCopy(Trame, 'Envoi de la trame ' + IntToStr(Ret));
if Trame[0] <> #0then
Synchronize(Traiter);
end;
end;
procedure TMonThread.WhenTerminated(Sender: TObject);
begin
Synchronize(Fin);
end;
procedure TMonThread.Fin;
begin
FForm.Ed_Loggin.Text := 'Terminé !';
end ;
end.
En dehors de l'ajout d'une méthode pour bien pouvoir observer l'arrêt du thread sur la fiche, la variable LaTrame a été avantageusement remplacée par le tableau de caractères. J'ai trouvé qu'il était inutile de dupliquer d'un PChar dans une string.
Ce code fonctionne, avec ou sans souris au dessus de la fiche, la fenêtre en arrière plan comme en avant plan mais également quand on déplace la fenêtre en cours d'exécution.
Teste le.
Si tout fonctionne aussi chez toi, c'est que ton problème vient soit de la dll, soit d'ailleurs.
May Delphi be with you !
<hr color ="#008000" />
Pensez à cliquer sur Réponse acceptée lorsque la réponse vous convient.
picolo5
Messages postés31Date d'inscriptionlundi 9 août 2004StatutMembreDernière intervention18 décembre 2006 10 août 2006 à 16:45
Il me semble bien que j utilise la bonne declaration de Synchronize, je ne trouve nulle part de version TThread.Synchronize(Sender,methode) uniquement TThread.Synchronize(methode)
cs_Forman
Messages postés600Date d'inscriptionsamedi 8 juin 2002StatutMembreDernière intervention 6 avril 20101 10 août 2006 à 20:22
Salut,
Peut-être que le problème vient de la façon dont tu lances le thread. Le code que tu as posté me parait tout à fait valide, mais il faudrait que tu postes aussi le source de la form pour voir s'il n'y a pas un problème là (par exemple si tu lances le thread dans un événement, et que tu fais un WaitFor dans l'événement).
Vous n’avez pas trouvé la réponse que vous recherchez ?
cs_Forman
Messages postés600Date d'inscriptionsamedi 8 juin 2002StatutMembreDernière intervention 6 avril 20101 10 août 2006 à 20:33
Après avoir relu la façon dont Borland a implémenté la méthode Synchronize, j'ai lu que lorsque l'application entre dans un état IDLE (en attente de messages), elle crée une procédure WakeMainThread qui fait ceci:
procedure TApplication.WakeMainThread(Sender: TObject);
begin
PostMessage(Handle, WM_NULL, 0, 0);
end;
Cette procédure est appelée (si assignée, donc si l'application est en mode idle) par tout thread souhaitant se synchroniser. Je me souviens avoir rencontré un problème semblable sous windows millenium: l'événement OnIdle de l'application n'était pas appelé correctement. Tu as quelle version de Windows?
Sinon, le problème peut venir de ta DLL. Que se passe-t-il lorsque tu remplaces les fonctions importées par des fonctions bidons et que tu ne charges pas la DLL?