Problème Thread

kwentinn Messages postés 27 Date d'inscription mardi 13 mai 2003 Statut Membre Dernière intervention 29 mars 2004 - 22 mars 2004 à 14:57
kwentinn Messages postés 27 Date d'inscription mardi 13 mai 2003 Statut Membre Dernière intervention 29 mars 2004 - 29 mars 2004 à 22:26
Salut à tous!
J'ai un programme qui doit utiliser un thread. J'ai donc créé un nouveau Thread, une nouvelle unité qui contient son code, et j'ai adapté mon code qui se faisait sur un bouton à ce thread. Actuellement, le thread n'arrive pas à fonctionner; j'ai l'impression qu'il s'arrête une dizaine de lignes après avoir démarré. Je vous met un bout du source de mon thread:
unit UThreadTraitement;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComObj, OleServer, Excel2000, Gauges, Menus, IniFiles;

type
  ThreadTraitement = class(TThread)
  private { Déclarations privées }
    procedure UpdateProgress;
  protected
    procedure Execute; override;

  end;
var  itemIndex: integer;
implementation

{ Important : les méthodes et propriétés des objets de la VCL peuvent uniquement
  être utilisés dans une méthode appelée en utilisant Synchronize, comme :

      Synchronize(UpdateCaption);

  où UpdateCaption serait de la forme

    procedure ThreadTraitement.UpdateCaption;
    begin
      Form1.Caption := 'Mis à jour dans un thread';
    end; }

{ ThreadTraitement }

uses Utypes, Unit1;

{ --- variables locales au thread -------------------------------------------- }
var
  i,j, modelepos: integer;
  StrTmp: String;
  Checked: boolean; { note si la case à cocher est cochée ou non }

{ ---------------------------------------------------------------------------- }

{ ---------------------------------------------------------------------------- }
procedure ThreadTraitement.UpdateProgress;
begin
  mainform.gauge1.Progress := mainform.Gauge1.Progress + 1;
end;
{ ---------------------------------------------------------------------------- }

{ -  EXECUTION DU THREAD  ---------------------------------------------------- }

procedure threadtraitement.execute;
var
  vide: integer;      { note le nb de lignes vides                             }
  NonValide: integer; { note le nb de lignes non valides càd supprimées        }
  Dialogue : integer; { enregistre le choix de l'utilisateur                   }

  DelLine : Boolean;    { variable permettant de savoir si la ligne en cours est
                         à supprimer ou non                                    }
  OuiPourTout: Boolean; { var permettant de savoir si on affiche la boite de
                          dialogue de confirmat° en cas d'erreur sur la ligne  }
  NonPourTout : Boolean;{ permet de savoir si la boite de dialogue doit être 
                          affichée et enregistre l'action à effectuer          }
  OLEOpened: boolean;   { permet de savoir si l'objet OLE a été ouvert ou non  }

Begin
//utiliser le modèle sélectionné pour la boucle for i:=1 to nbcolonnes
//initialisation des variables:
NonValide := 0;
OuiPourTout := False;
NonPourTout := False;
{utilisation d'un bloc try ... except pour intercepter les erreurs }
try
  //initialisation des variables:
  Infos.RefArt := '';
  Infos.RefFour := '';
  Infos.Des := '';
  Infos.PA := 0;
  { ------ boucle qui parcourt ttes les lignes du fichier excel -------------- }
  For i := 1 to NbLignesXL Do
    begin//3
      //la jauge est incrémentée de 1 à chaque passage:
      synchronize(updateProgress);
      //réinitialisation des variables:
      StrTemp := '';
      vide := 0;
      Infos.Des :='';
      Infos.RefArt := '';
      Infos.RefFour := '';
      { ---- boucle qui parcourt ttes les colonnes d'1 ligne ----------------- }      For j :1 to Modele.NbCol do //de i 1 jusqu'au nbre de col du modèle
        Begin//4
          { on utilise StrTemp (Chaîne temporaire) qui contient
            le contenu de la case en cours du fichier excel ouvert }
          { on récupère les infos de la feuille XL via le
            tableau dynamique }
          StrTemp := TabDyn[i,j];
          If StrTemp = '' Then//StrTemp est vide
            vide := vide + 1  { lorsqu'un champ est vide, on ajoute 1 à vide }
          Else
            Begin//5
              If mainform.CheckBox1.Checked Then
                SearchMotCle(FileMotsCles,MotCle,DelLine)
              ELSE
                Begin //checked
                  { j est la position en cours lue
                    si j = au n° d'1 champ , alors on enregistre
                    son contenu...Mais attention aux exceptions..
                    (on utilise delchar pour suppr les car illégaux):
                    ici, on aurait pu utiliser un case, mais il
                    n'est pas accepté par delphi pr des var
                    de type entier}
                  { Champ Référence Fournisseur : }
                  If j = Modele.RefFour Then
                    begin
                      DelChar(StrTemp);
                      Infos.RefFour := StrTemp;
                    end
                  Else
                  { champ Référence Article : }
                  If j = Modele.RefArt Then
                    Begin
                      DelChar(StrTemp);
                      Infos.RefArt := StrTemp;
                      StrTemp := '';
                    End
                  Else
                  { champ désignation: }
                  If j = modele.Des then
                    begin
                      Infos.Des := StrTemp;
                      StrTemp := '';
                    end
                  else
                  { Champ Prix d'achat : }
                  if j = modele.PA then
                    begin //p.a.
                      Try
                        Infos.PA := StrToFloat(StrTemp);
                        StrTemp := '';
                      Except On EConvertError Do
                        begin
                        { si l'utilisateur a cliqué sur le bouton 'Oui pour tout'
                          alors on n'affiche pas la boite de dialogue et on
                          supprime la ligne }
                          If OuiPourTout = True Then
                            DelLine  := True
                          Else
                          { S'il a choisi 'non pour tout' alors on n'affiche pas la
                            boite de dialogue et on ne supprime pas la ligne}
                          If NonPourTout = True Then
                            begin
                              DelLine := False;
                              infos.PA := 0;
                            end
                          Else
                          { Cas où l'utilisateur n'a pas encore eu la boite de dialogue
                            de confirmation }                          If (OuiPourTout false) AND (NonPourTout false) Then
                            Begin
                              { la variable dialogue enregistre le choix de l'utilisateur:
                                oui: dialogue = 6
                                non: dialogue = 7
                                oui pour tout: dialogue = 10
                                non pour tout: dialogue = 9 }
                              dialogue := MessageDlg('A la ligne ' + IntToStr(i) + ', il y a une erreur de type.' +#10+#13+ 'Pour le champ "Prix d''achat", la valeur entrée est '+ StrTemp + #10+#13+ 'Cette ligne contient les informations suivantes :'+ #10 + #13 + 'Référence Article :' + Infos.RefArt + #10 + #13 +'Référence Fournisseur:' + Infos.RefFour + #10 + #13 + 'Désignation: ' + Infos.Des + #10+#13+ 'Prix d''achat:' + StrTemp +#10+#13+ 'Voulez-vous supprimer cette ligne?',mtConfirmation,[mbYesToAll,mbNoToAll,mbNo,mbYes],0);
                              If dialogue = 6 Then
                                DelLine := True
                              Else
                              If dialogue = 7 then
                                begin
                                  DelLine := False;
                                  infos.PA := 0;
                                end
                              Else
                              If dialogue = 10 then
                                OuiPourTout := True
                              Else
                              If dialogue = 9 then
                                NonPourTout  := False;
                            End;
                        end;
                      End;//try
                    end;//p.a.
                End; //checked
            End;//5
        End;//4
      { ------ fin du parcours des colonnes du fichier --------------------- }
      //si les chps les + importants sont vides, on suppr la ligne      If (Infos.Des '') and (infos.RefArt '')
        and(Infos.RefFour = '') Then
        DelLine := True;
      //si vide = le nb de col du modèle, alors
      //la ligne est ignorée
      If vide = Modele.NbCol  Then
        DelLine := True
      Else
      //s'il n'y a qu'un champ de rempli, on demande à l'utilisateur
      If vide = Modele.NbCol - 1 Then
        begin
          {Permettre à l'utilisateur de choisir oui pour tous:
          Par ex avec une variable de type booléen}          If (OuiPourTout False) AND (NonPourTout False) Then
            Begin
              { boite de dialogue demandant à l'utilisateur s'il
                faut supprimer la ligne ou non:}
              { la variable dialogue enregistre le choix de l'utilisateur:
                oui: dialogue = 6
                non: dialogue = 7
                oui pour tout: dialogue = 10
                non pour tout: dialogue = 9 }
              Dialogue := MessageDlg(IntToStr(vide) + ' champs (sur ' + IntToStr(Modele.NbCol) + ') de la ligne ' + IntToStr(i)+ ' sont vides.'+ #10+#13+'Cette ligne contient les informations suivantes :'+ #10 + #13 + 'Référence Article :' + Infos.RefArt + #10 + #13 +'Référence Fournisseur:' + Infos.RefFour + #10 + #13 + 'Désignation: ' + Infos.Des + #10+#13+ 'Prix d''achat:' + FloatToStr(Infos.PA) +#10+#13+ 'Voulez-vous supprimer cette ligne?',mtConfirmation,[mbNo,mbYes,mbYesToAll,mbNoToAll],0);
              If Dialogue = 6 Then  // oui
                DelLine := True
              Else
              If Dialogue = 7 Then // non
                DelLine := False
              Else
              If Dialogue = 10 Then // oui pour tout
                OuiPourTout := True
              Else
              If Dialogue = 9 Then  // non pour tout
                NonPourTout := True;
            End
          Else
          If OuiPourTout = True Then
            DelLine := True
          Else
          If NonPourTout = True Then
            DelLine := False;
        end;
      If DelLine = False Then
        begin
          If Modele.PA = 0 Then { on n'écrit pas le p.a. }
            SL.Add(Infos.RefArt + #9 + Infos.RefFour + #9 + rien + #9 + Rien + #9
            + Rien + #9 + Rien + #9 + Rien + #9 + Rien + #9 + Rien + #9 + Rien
            + #9 + Rien + #9 + Rien + #9 + Rien + #9 + Infos.Des + #9 +
            Modele.ProdFam + #9 + rien + #9 + rien +  #9 + '2')
          Else
            SL.Add(Infos.RefArt + #9 + Infos.RefFour + #9 + FloatToStr(Infos.PA)
            + #9 +Rien + #9 + Rien + #9 + Rien + #9 + Rien + #9 + Rien + #9 +
            Rien + #9 + Rien + #9 + Rien + #9 + Rien + #9 + Rien + #9 + Infos.Des
            + #9 + Modele.ProdFam + #9 + rien + #9 + rien +  #9 + '2');
        end
      Else
        NonValide := NonValide + 1; { suppression de la ligne: on n'écrit rien }
    end;//3
  { ----- fin du parcours du tableau dynamique ------------------------------- }
  mainform.ComboBox1.Clear; //efface le contenu de la combobox
  MessageDlg('Nombre de ligne(s) supprimée(s) : ' + IntToStr(NonValide)+ #13+ 'Nombre de lignes écrites: '+ IntToStr(SL.Count) + #10 + #13 + 'Opération Terminée'+#13+ 'Veuillez sélectionner un fichier pour sauvegarder.',mtInformation,[mbOK],0);
  If mainform.SaveDialog1.Execute Then
    SL.SaveToFile(mainform.SaveDialog1.FileName); //sauvegarde la stringlist dans un fichier texte
  mainform.gauge1.Progress := 0;
  mainform.gauge1.MaxValue := 1;
  mainform.gauge1.Visible := False;
  MainForm.Close;//ferme la fenêtre
  CloseFile(FCI);
 except
  begin
    MessageDlg('Une erreur s''est produite...',mtError,[mbOk],0);
    exit;
  end;
end ;
end;
{ ---------------------------------------------------------------------------- }
end.


Merci 8-)

@+
|< \\/\\/ E |\\| T | |\\| |\\|

3 réponses

cs_Delphiprog Messages postés 4297 Date d'inscription samedi 19 janvier 2002 Statut Membre Dernière intervention 9 janvier 2013 32
22 mars 2004 à 20:47
Le code est complètement à revoir sauf la procédure UpdatProgress.

Dans la méthode Executre du thread, tu fais des références à Mainform alors que Borland précise ceci :
{ Important : les méthodes et propriétés des objets de la VCL peuvent uniquement être utilisés dans une méthode appelée en utilisant Synchronize, comme :

Synchronize(UpdateCaption);

où UpdateCaption serait de la forme

procedure ThreadTraitement.UpdateCaption;
begin
Form1.Caption := 'Mis à jour dans un thread';
end; }


Libre à chacun de ne pas tenir compte de cet avertissement mais, dans ce cas, il ne faut pas s'étonner qu'un thread secondaire batte de l'aile.

Enfin, comme le corps de la méthode Execute fait appel à des variables, structures ou objets déclarées (dans d'autres unités ? voir Infos, par exemple), il est difficile d'aider davantage que de donner des recommandations.

Un ultime conseil : pour améliorer la lisibilité du code et son efficacité, il serait judicieux de remplacer des constructions à base de if à rallonge par des structures Case comme :

If dialogue = 6 Then
DelLine := True
Else
If dialogue = 7 then
begin
DelLine := False;
infos.PA := 0;
end
Else
If dialogue = 10 then
OuiPourTout := True
Else
If dialogue = 9 then
NonPourTout := False;

par :
case dialogue of
   6 : DelLine := True
   7 :
       begin
          DelLine := False;
           infos.PA := 0;
        end;
   10 : OuiPourTout := True
     9 : NonPourTout := False;
end; {case dialogue}

Quand Dialogue vaut 9, il n'est effectué qu'un seul test au lieu de 4 !
May Delphi be with you
0
kwentinn Messages postés 27 Date d'inscription mardi 13 mai 2003 Statut Membre Dernière intervention 29 mars 2004
23 mars 2004 à 07:44
Merci bien de me donner ces précieux conseils!!! :) Je vais essayer de mettre en pratique ce que tu m'as dit, je pense que ça devrait marcher :)

"Le code est complètement à revoir sauf la procédure UpdatProgress." > oula j'espère que je vais pas tout me retaper... car sinon ça serait vraiment bien long...

Sur ce, merci encore

@+
|< \\/\\/ E |\\| T | |\\| |\\|
0
kwentinn Messages postés 27 Date d'inscription mardi 13 mai 2003 Statut Membre Dernière intervention 29 mars 2004
29 mars 2004 à 22:26
J'ai passé pas mal de temps à essayer de déboguer le thread, mais rien n'y fait! ça ne marche pas... Si qqn a la solution miracle, qu'il me la donne, sinon, je mettrai pas de thread dans mon prog..

Merci

@+
|< \\/\\/ E |\\| T | |\\| |\\|
0
Rejoignez-nous