Thread : Synchronize Bloqué !!!!

Résolu
picolo5 Messages postés 31 Date d'inscription lundi 9 août 2004 Statut Membre Dernière intervention 18 décembre 2006 - 10 août 2006 à 15:53
picolo5 Messages postés 31 Date d'inscription lundi 9 août 2004 Statut Membre Dernière intervention 18 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;


interface


uses
  Classes,Windows,Unit1 ;




type
  MonThread = class(TThread)
  private
    FForm : TForm1;
    { Déclarations privées }
  protected
    procedure Execute; override;
    procedure Traiter;
    procedure Sync;
    public
    constructor Create(Form : TForm1);


  end;


implementation


{ Function importées de la DLL}
function OpenSession(loggin : PChar; pswd : PChar): integer; StdCall; external 'Test.dll';
function Init(portServSPAD : integer ;portServTPAD : integer): integer; StdCall; external 'Test.dll';
function CloseSession(): integer; StdCall; external 'Test.dll';
function GetMessage(messages : PChar): integer; StdCall; external 'Test.dll';


 


{ MonThread }


var
    trame : array[0..1024] of char;
    LaTrame : string;


procedure MonThread.Traiter;
begin
   FForm.Ed_Loggin.Text := 'Grrrrrrrr';
   FForm.TraiterTrame(Trame);
end;




constructor MonThread.Create(Form: TForm1);
  begin
    inherited Create(False);
    FForm := Form;
    FreeOnTerminate := True;
  end;


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;


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é' ??

Au secours !!!!!

Merci ;)
A voir également:

6 réponses

cs_Delphiprog Messages postés 4297 Date d'inscription samedi 19 janvier 2002 Statut Membre Dernière intervention 9 janvier 2013 32
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.
3