IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Delphi Discussion :

Transformer une procedure en thread


Sujet :

Langage Delphi

  1. #1
    Membre éprouvé Avatar de defluc
    Homme Profil pro
    Architecte
    Inscrit en
    Mai 2002
    Messages
    1 383
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : Belgique

    Informations professionnelles :
    Activité : Architecte

    Informations forums :
    Inscription : Mai 2002
    Messages : 1 383
    Points : 1 199
    Points
    1 199
    Par défaut Transformer une procedure en thread
    Bonjour,

    Je n'ai jamais utilisé les threads mais après avoir lu la faq, cela me parait intéressant pour mon application.

    Je voudrais savoir si je pourrais transformer un procedure remplissant une table d'une base de données après avoir lu un fichier .txt pour et manipulé ses données.
    La procedure fait appel à des variables locales et globales ainsi qu'à des fonctions que j'ai créées. Elle affiche une fiche avec barre de progression.

    Merci d'avance

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 563
    Points : 25 165
    Points
    25 165
    Par défaut
    Consulte l'aide au sujet de l'Objet TThread

    tout ton code sera dans le Execute surchargé !

    sépare ton code en plusieurs parties :
    1- Manipulation DB
    2- Manipulation Fichier
    3- Traitement
    4- Affichage

    1- Tu as deux solutions pour la DB
    Soit une connexion spécifique au Thread, crée dans celui-ci, soit partager la connexion de l'application (perte d'intéret du thread), ... tu peux regrouper les Objets Connexion, Table, Query dans un DataModule, et tu crées une instance de ce DataModule par Thread

    2- Rien d'extraordinaire pour les fichiers, tout doit être dans le thread, Open, Close, Read, Write ...

    3- Rien d'extraordinaire, sauf évite les variables globales au profit de variables dans la classe (champs privées) hérité de TThread ...

    4- Si veux que ton thread ne soit pas ralenti par l'affichage, tu peux faire un echange de message personalisé avec PostMessage (avec lParam et wParam, tu faire passer un entier par exemple, Position et Max d'une progressBar, PostMessage n'est pas bloquant), si tu dois afficher des messages, tu peux utiliser Synchronise (passage par champs protégés et accesseur publiques) ou SendMessage (bloquant) pour envoyer un pointeur de chaine par exemple ...



    En fait, commence par réécrire ta procédure comme étant une méthode d'objet ... SANS te préocupper de la notion de thread, mais en pensant tout l'ensemble de ton traitement sur la forme d'objet qui s'utilise les uns les autres ... appelant méthode et propriété avec accesseurs ...

    Pour tes variables globales, idem,
    Si tu dois les modifier en cours de route, encapsuler tes variables globales dans une classe (voir singleton sur le forum) pour automatiser la gestion des verrous (Section Critiques, Synchronise, ...)
    Si tu ne fait que les consulter, le mieux serait de passer le contenu des variables en paramètres du constructeur ...

    Personnellement, j'ai fait aussi du procédurale pour des Threads, mais chaque Thread avait une variable globale (comme pour form par défaut), et les procédures utilisant toujours cette variable et accédait à tout ce qu'il avait besoin comme le DataModule ou les propriétés protégés via Section Critique ... je faisais bcp moins d'objet à l'époque et puis j'avais tellement de traitement que si j'avais mis tous dans la même unité, j'aurais dépassé les 30000 lignes de code (pilotage de machine de tri en temps réel ...), trop lourd, j'ai préféré, faire plusieurs unités regroupant les fonctions par thèmes (gestion des lampes et écran LCD, gestion des tapis roulants, gestion des baies de stockages, gestion des trolleys, gestion des boutons pressoirs, ...)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    procedure InitThread();
    begin
      ...   
      TreatThread := TTreatThread.Create(True);
      ...
    end;

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    TreatThread.DataModule.TableTruc.FieldByName('Champ1').AsInteger := 0;
    TreatThread.DataModule.TableTruc.FieldByName('Champ2').AsInteger := 1;

  3. #3
    Membre expert
    Avatar de aityahia
    Homme Profil pro
    CIEPTAL CARS SPA
    Inscrit en
    Mars 2006
    Messages
    1 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Algérie

    Informations professionnelles :
    Activité : CIEPTAL CARS SPA
    Secteur : Transports

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 938
    Points : 3 329
    Points
    3 329
    Par défaut
    effectivement c'est tous a fait possible
    tu trouvera ici et ici deux tuto te permettant de comprendre et d'utiliser les threads

    moi personellement j'utilise le composant TIdThread de Indy.

  4. #4
    Membre éprouvé Avatar de defluc
    Homme Profil pro
    Architecte
    Inscrit en
    Mai 2002
    Messages
    1 383
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : Belgique

    Informations professionnelles :
    Activité : Architecte

    Informations forums :
    Inscription : Mai 2002
    Messages : 1 383
    Points : 1 199
    Points
    1 199
    Par défaut
    Cela me parait bien compliqué de concevoir une première utilisation d'un thread avec un procédure éprouvée mais relativement élaborée.

    Alors, quelques conseils ne seraient pas malvenus.

    Voici la procédure en question.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    Procedure TCadaDataModule.FillTableProprio(CadaRepert:String);
    Var
      Nom, AdresseProprio, CodePostal, Localite, DroitProprio:String;
      Daa, CodeNext, DivCode, LenStr, DelimPos, NoField : Integer;
      Fichier : TextFile ;
      Chaine, Champs : string;
      NoRec, NbrRec :LongInt;
      InitTime, InstTime, RemainTime, TotTime : TTime;
    Begin
    if TableExist('TEMPTABLE') Then SuppressTable('TEMPTABLE');
    with Zquery.Sql do  // Création de la table temporaire des biens
     begin   // Add(Name; DataType: TFieldType; Size; Required);
           Clear;      // Description des champs
           Add('Create Table TempTable (');
           Add('DIVCODE        INTEGER,');         // Field8
           Add('DAA            INTEGER,');         // Field8
           Add('NOM            VARCHAR(180),');          // Field1
           Add('ADRESSEPROPRIO VARCHAR(44),'); // Field4
           Add('CODEPOSTAL     CHAR(4),');          // Field5
           Add('LOCALITE       VARCHAR(38),');           // Field7
           Add('CODENEXT       SMALLINT,');         // Field9
           Add('DROITPROPRIO   VARCHAR(45)');      // Field10
           Add(') ;');
      end;
     Zquery.ExecSQL;
     AssignFile(Fichier,CadaRepert+'Pe.txt');
     Reset(Fichier);
     NbrRec := Ceil(FileSize(Fichier)*1.21);
     FormProgress.LabelTask.Caption := MainForm.StrList[181];
     FormProgress.StepLabel.Caption := MainForm.StrList[182];
     FormProgress.StepLabel.Color := $0080FF80;
     FormProgress.OperLabel.Caption := MainForm.StrList[183];
     FormProgress.OperLabel.Color :=$0080FF80;
     FormProgress.ProgressBar.Step := 1;
     FormProgress.ProgressBar.Max := NbrRec;
     NoRec:=0;
     InitTime := Now;
       Zquery.Sql.Clear;
       ZQuery.SQL.Add('INSERT INTO TempTable (');
       ZQuery.SQL.Add('DivCode,Daa,Nom,AdresseProprio,CodePostal,Localite,CodeNext,DroitProprio) ');
       ZQuery.SQL.Add('Values (');
       ZQuery.SQL.Add(':DivCode,:Daa,:Nom,:AdresseProprio,:CodePostal,:Localite,:CodeNext,:DroitProprio) ');
    While not System.eof(Fichier) Do   //  Lecture des enregistrements
      Begin
       Inc(NoRec);
       Nom:='';AdresseProprio:='';CodePostal:='';Localite:='';Daa:=0;
       DivCode:=0;CodeNext:=0;DroitProprio:='';
       NoField:=1;
       ReadLn(Fichier,Chaine);
       DelimPos := Pos(';',Chaine);
       LenStr:=1  ;
       While (NoField < 9) and (DelimPos > 0 ) do //  Lecture des champs
       Begin
         DelimPos :=  Pos(';',Chaine);
         if DelimPos = 0 Then DelimPos := LenStr;
         Champs := Copy(Chaine,0,DelimPos -1) ;
         LenStr:= Length(Champs);
         Case NoField of    //  Assignation des champs
            1: Nom := Champs;
            3: begin
                DivCode:= StrToInt(Copy(Champs,1,5));
                Daa:=StrToInt(Copy(Champs,6,5));
               end;
            4: CodeNext:= StrToInt(Champs);
            5: Begin
                 CodePostal := Copy(Champs,1,5);
                 Localite := Copy(Champs,6,LenStr-5);
               end;
            6: AdresseProprio := Champs;
            8: DroitProprio := Champs;
         end;
         LenStr := Length(Chaine);
         Chaine := Copy(Chaine,DelimPos+1,LenStr-DelimPos);
         Inc(NoField);
       end; //Fin  Lecture des champs
       Zquery.Params[0].AsInteger:=DivCode;
       Zquery.Params[1].AsInteger:=Daa;
       Zquery.Params[2].AsString:=Nom;
       Zquery.Params[3].AsString:=AdresseProprio;
       Zquery.Params[4].AsString:=CodePostal;
       Zquery.Params[5].AsString:=Localite;
       Zquery.Params[6].AsSmallInt:=CodeNext;
       Zquery.Params[7].AsString:=DroitProprio;
       Zquery.ExecSQL;
     
       FormProgress.ProgressBar.StepIt;
       InstTime := Now-InitTime ;
       TotTime := EndStepTime + InstTime;
       RemainTime := InstTime/NoRec*(NbrRec-NoRec) ;
       FormProgress.LabelElapsTimeDigit.Caption := TimeToStr(InstTime);
       FormProgress.LabelRemainTimeDigit.Caption:=TimeToStr(RemainTime);
       FormProgress.LabelTotalElapsTimeDigit.Caption := TimeToStr(TotTime);
    end;    // Fin Lecture des enregistrements
     CloseFile(Fichier);
     
     ZQuery.SQL.Clear;
     ZQuery.SQL.Add('INSERT INTO "TableProprio" (');  // Remplissage de la Table "TableProprio" 
     ZQuery.SQL.Add('Nom, AdresseProprio, CodePostal, Localite, DroitProprio, Article) ');
     ZQuery.SQL.Add('SELECT ');
     ZQuery.SQL.Add('TempTable.Nom as Nom, TempTable.AdresseProprio as AdresseProprio, ');
     ZQuery.SQL.Add('TempTable.CodePostal as CodePostal, TempTable.Localite as Localite, ');
     ZQuery.SQL.Add('TempTable.DroitProprio as DroitProprio, ');
     ZQuery.SQL.Add('((TableDiv.Div*100000)+ TempTable.Daa) as Article ');
     ZQuery.SQL.Add('FROM TempTable INNER JOIN TableDiv ON ');
     ZQuery.SQL.Add('TempTable.DivCode = TableDiv.DivCode');
     Zquery.ExecSQL  ;
     Zquery.SQL.Clear;
     TableProprio.Active := True;
    end;

  5. #5
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 563
    Points : 25 165
    Points
    25 165
    Par défaut
    Citation Envoyé par defluc Voir le message
    Alors, quelques conseils ne seraient pas malvenus.
    Je pensais en avoir donné !?
    Etudie l'Objet TThread via l'Aide, et en faisant quelques essais isolés ...

    Au vu de la fonction, il s'agit d'une méthode dans un DataModule, lance un thread, crée une nouvelle instance du Datamodule (connexion, initialiation diverses, en recopiant les données du DataModule principal), et lance la fonction, ...

    Pour FormProgress, fait des fonctions comme
    SetLabelTaskCaption, SetLabelTaskColor, SetProgresBarStep, ... qui mettrons dans des variables tampons les différents paramètres, puis un appel à Synchronize

    pour ton découpage de Champs, tu pourrais utiliser ma fonction ExplodeLazy, cela simplifierai\optimisera ton Code ...

    PS : l'Indentation du code est comme ça dans le source, ou c'est le copier dans le forum qui l'a altéré ? Car cela mérité un grand nettoyage, c'est très brouillon ... peu maintenable ... si un jour un autre doit reprendre ce travail, je le plainds, moi aussi, j'ai ce genre de code à maintenir, et ça coute du temps pour rien ...

  6. #6
    Membre éprouvé Avatar de defluc
    Homme Profil pro
    Architecte
    Inscrit en
    Mai 2002
    Messages
    1 383
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : Belgique

    Informations professionnelles :
    Activité : Architecte

    Informations forums :
    Inscription : Mai 2002
    Messages : 1 383
    Points : 1 199
    Points
    1 199
    Par défaut
    Bon, je vais m'y mettre.
    Quant à l'indentation, c'est une chose à laquelle je suis très attentif et je ne sais pas ce qui s'est passé.

    Merci de ton aide

Discussions similaires

  1. Transformer une procedure stockée en script PL/SQL?
    Par arnauann dans le forum PL/SQL
    Réponses: 4
    Dernier message: 28/09/2007, 14h46
  2. Execution d'une procedure avec TNotifyEvent;
    Par Chupakabra dans le forum Langage
    Réponses: 2
    Dernier message: 30/01/2003, 14h50
  3. Declaration Type ds une procedure
    Par Qwazerty dans le forum Langage
    Réponses: 6
    Dernier message: 28/08/2002, 09h09
  4. [TP]code asm dans une procedure
    Par M.Dlb dans le forum Turbo Pascal
    Réponses: 3
    Dernier message: 17/08/2002, 20h43
  5. Reprendre une procedure dans une autre ?
    Par Poisson Rouge dans le forum Langage
    Réponses: 3
    Dernier message: 17/07/2002, 22h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo