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

 Delphi Discussion :

Thread et DBGrid


Sujet :

Delphi

  1. #1
    Membre du Club
    Thread et DBGrid
    Salut tous le monde j'ai réalisé une petite application qui fait un simple traitement, j'ai utilisé un thread pour que l'application ne reste pas figé mais le problème qui se pose c'est que la DBGrid durant le parcours des enregistrements de la table elle reste figé visuellement voila pour le code du thread

    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
    procedure thread1.Execute;
    var
    i:integer;
    code:string;
    begin
    form1.progressbar1.Position:=1;
    form1.progressbar1.Max:=form1.abstable1.RecordCount;
    form1.abstable1.First;
     
    while not form1.abstable1.Eof do
    begin
    form1.label1.Caption:='Traitement en cours ...';
    form1.label1.Update;
    form1.progressbar1.Position:=form1.progressbar1.Position+1;
     
    for i:=1 to 31 do
    begin
    code:=form1.abstable1['Jour_'+inttostr(i)];
    form1.absquery1.Close;
    form1.absquery1.SQL.Clear;
    form1.absquery1.SQL.Add('select * from table2 where code='+QuotedStr(code));
    form1.absquery1.Open;
    form1.abstable1.Edit;
    if not form1.absquery1.IsEmpty then
    form1.abstable1['Jour_'+inttostr(i)]:=form1.absquery1['heure']
    else
    form1.abstable1['Jour_'+inttostr(i)]:=code;
    form1.abstable1.Post;
    end;
    form1.abstable1.Next;
    end;
     
    form1.label1.Caption:='Traitement terminé';
    form1.label1.Update;
    form1.workerthread.terminate;
    end;


    Alors comment fixer ce problème.

    Merci.

  2. #2
    Modérateur

    Il me semble que la VCL n'est pas threadsafe et que les appels à des composants VCL à partir d'un thread doit passer par un Synchronize.
    Delphi 5 Pro - Delphi 10.3.2 Rio Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  3. #3
    Membre du Club
    Citation Envoyé par tourlourou Voir le message
    Il me semble que la VCL n'est pas threadsafe et que les appels à des composants VCL à partir d'un thread doit passer par un Synchronize.
    Merci tourlourou mais comment faire peux tu me donner un coût de pousse par un bout de code.

  4. #4
    Modérateur

    Delphi 5 Pro - Delphi 10.3.2 Rio Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  5. #5
    Membre du Club
    Voila ce que j'ai fait comme code mais ça n'a rien donner de nouveau

    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
    procedure thread1.GetRes;
    var
    i:integer;
    code:string;
    begin
    form1.progressbar1.Position:=1;
    form1.progressbar1.Max:=form1.abstable1.RecordCount;
    form1.abstable1.First;
     
    while not form1.abstable1.Eof do
    begin
    form1.label1.Caption:='Traitement en cours ...';
    form1.label1.Update;
    form1.progressbar1.Position:=form1.progressbar1.Position+1;
     
    for i:=1 to 31 do
    begin
    code:=form1.abstable1['Jour_'+inttostr(i)];
    form1.absquery1.Close;
    form1.absquery1.SQL.Clear;
    form1.absquery1.SQL.Add('select * from table2 where code='+#39+code+#39);
    form1.absquery1.Open;
    form1.abstable1.Edit;
    if not form1.absquery1.IsEmpty then
    form1.abstable1['Jour_'+inttostr(i)]:=form1.absquery1['heure']
    else
    form1.abstable1['Jour_'+inttostr(i)]:=code;
    form1.abstable1.Post;
    end;
    form1.abstable1.Next;
    end;
     
    form1.label1.Caption:='Traitement terminé';
    form1.label1.Update;
     
    end;
     
    procedure thread1.Execute;
    begin
    Synchronize(GetRes);
    form1.workerthread.terminate;
    end;

  6. #6
    Modérateur

    Je pense que le Synchronize de la procédure globale bloque la fiche ; il conviendrait de scinder en plusieurs appels de procédures, chacun synchronisé.
    Delphi 5 Pro - Delphi 10.3.2 Rio Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  7. #7
    Rédacteur/Modérateur

    Bonjour,

    La première chose qu'indique Olaf Monien dans son excellente intervention sur les Threads lors des Delphi CE Bootcamp Delphi 2018 c'est qu'il ne faut pas interférer avec les éléments de l'interface utilisateur (sauf par certains biais évidemment). Je ne saurais que trop vous recommander de visionner ces cours (gratuits)


    En plus je trouve votre traitement dérangeant ! Êtes-vous sûr que la partie traitement des données ne pourrait pas se faire par l'intermédiaire d'un SQL Update (plus d'infos sur les tables à fournir) ?

    Déjà, je me pose une question de quel SGBD s'agit-il ?


    Plusieurs choses retiennent mon attention
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    form1.absquery1.Close;
    form1.absquery1.SQL.Clear;
    form1.absquery1.SQL.Add('select * from table2 where code='+#39+code+#39);
    form1.absquery1.Open;


    Sera mieux transformée en

    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
    // création d'une requête en mode runtime, AQuery à déclarer en tant que variable  
    AQuery:=TQuery.Create;
    try
      .. // indiquer la connexion
      AQuery.SQL.text:='select * from table2 where code=:C';
      AQuery.Prepare;
    
      for i:=1 to 31 do
       begin
         Code:=format('JOUR_%d',[i]); 
         AQuery.Active:=False;
         AQuery.ParamByName('C').asString:=Code;
         AQuery.Active:=True;
         // suite du traitement
    
      end;
    finally
      AQuery.Free;
    end;


    Ensuite,
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    if not form1.absquery1.IsEmpty then
    form1.abstable1['Jour_'+inttostr(i)]:=form1.absquery1['heure']

    Si absQuery1 retourne plus d'un enregistrement quelle heure sera prise, la première, la dernière ou la max ? j'aurai tendance à dire la max
    le SQL Deviendrait donc
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
     
      AQuery.SQL.text:='select max(heure) from table2 where code=:C';
    La seule chose absolue dans un monde comme le nôtre, c'est l'humour. » Albert Einstein

    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Tokyo, Rio, Sidney) et peut être quelques autres
    SGBD : Firebird 2.5, 3, SQLite
    générateurs Etats : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Ubuntu, Androïd

  8. #8
    Membre émérite
    Je peux te donner une solution. Tu travailles sur quelle version de delphi ?

  9. #9
    Membre du Club
    Bonjour
    Citation Envoyé par SergioMaster Voir le message
    Êtes-vous sûr que la partie traitement des données ne pourrait pas se faire par l'intermédiaire d'un SQL Update (plus d'infos sur les tables à fournir) ?
    J'ai essayé de la traiter par SQL mais ça a donner presque le même résultat

    Citation Envoyé par SergioMaster Voir le message

    Déjà, je me pose une question de quel SGBD s'agit-il ?
    Pour le SGBD que j'utilise c'est absolute database

    Citation Envoyé par SergioMaster Voir le message
    Si absQuery1 retourne plus d'un enregistrement quelle heure sera prise
    Pour la Query j'ai assuré qu'elle ne retourne qu'une seule ligne.

    Dans cette application j'ai une table des travailleurs qui est mytable qui contient 2810 enregistrements et une autre table qui contient les codes des heures supplémentaires (elle contient deux colonnes: code et heure) par exemple: code= MS -> Heure= 11

    le but de cette application c'est de chercher dans mytable et remplace les codes par des heures dans les 31 jours du mois.

  10. #10
    Membre du Club
    Citation Envoyé par ALWEBER Voir le message
    Tu travailles sur quelle version de delphi ?
    J'utilise la version 7 de borland

###raw>template_hook.ano_emploi###