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

 Delphi Discussion :

[D7] Fonctionnement Thread


Sujet :

Delphi

  1. #1
    Membre chevronné
    Avatar de Droïde Système7
    Homme Profil pro
    Inscrit en
    Septembre 2003
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 2 276
    Points : 1 930
    Points
    1 930
    Par défaut [D7] Fonctionnement Thread
    Bonjour

    J'ai besoin d'un Thread dans un programme traitant un certain nombre de lignes via une StringList, composée elle-même de plusieurs boucles de recherches/comparaisons/ajouts/deletes ; etc.

    Autant dire que passé un certain nombre de lignes ; le programme se fige un peu, mais ne plante jamais et heureusement. Sauf qu'en ce cas ; ça prend pas mal de temps

    J'ai passé du temps à regarder et tester des codes divers et variés. Mais manquait toujours « une pièce » afin d'aller jusqu'au bout

    Présentement j'épluche ce tuto DVP :
    https://delphi.developpez.com/faq/?page=Thread

    1. J'ai créé une fiche secondaire ainsi qu'indiqué

    2. En fiche principale de l'interface de mon programme à traiter, j'ai disposé dans la procédure gérant le traitement du splitage en question :

    La déclaration en 'var' : MyThread: TTestThread

    Juste avant le traitement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MyThread := TTestThread.Create(False);
    Et juste après la fin du traitement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    // On demande au thread de s'arrêter "proprement". 
    MyThread.Terminate; 
    // Maintenant, on attend sa fermeture réelle. 
    ExitCode := MyThread.WaitFor;
    Je précise que si je lance mon programme, tout est RAS donc aucun plantage.

    Me reste alors à lancer le Thread et si le lis bien, pour lancer ce Thread faut écrire une commande comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MyThread.Synchronize(UpdateForm);
    Mais c'est là que je bute

    Pouvez-vous svp me donner un petit coup de pouce ?
    Mais au plus simple sans rien trop compliquer hein

    Merci de vos lumières

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 649
    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 649
    Points : 25 397
    Points
    25 397
    Par défaut
    Citation Envoyé par Droïde Système7 Voir le message
    Je précise que si je lance mon programme, tout est RAS donc aucun plantage.

    Me reste alors à lancer le Thread et si le lis bien, pour lancer ce Thread faut écrire une commande comme cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MyThread.Synchronize(UpdateForm);


    Synchronize c'est pour utiliser le MainThread depuis le thread secondaire.
    C'est bloquant, c'est a utiliser avec parcimonie.

    Un thread se lance via Start() mais c'est inutile dans ton cas avec un TTestThread créé en CreateSuspended à False, il se lance après la fin du constructeur.



    A quoi sert le Terminate() ?
    C'est pour abandonner le traitement en cours de route ? Si oui, Utilise un TEvent et rédéfini TerminatedSet : A lire "TThread.Suspend et TThread.Resume deprecated " .. mais encore ? te donnera un bon exemple d'interaction avec un Thread et le MainThread (Form principale)

    Si tu as une TStringList a parcourir, utiliser un Gestionnaire d'évènement OnTerminate, le Thread va s'arrêter tout seul une fois la liste parcourue.
    Le Terminate n'a pas de sens en dehors d'un abandon prématuré.



    Attention Insert et Delete sur une TStringList partagée par plusieurs Threads !
    Prévoir des sections critiques car sinon tu risques d'avoir des surprises
    liste au contenu corrompue,
    - le delete qui est une opération très lente de copie du tableau de pointeur, tu auras des trous inexpliqués, c'est invisible et sournois.
    - l'ajout là c'est potentiellement une réallocation (voir Grow / Capacity), en simultané, c'est une opération de pointeur incorrecte, ça plantera



    Combien de lignes dans la TStringList ? des millions ?
    As-tu déjà une version mono-thread qui fonctionne, est-elle lente ?

    Qu'elle est lien avec la fenêtre secondaire, une barre de progression ?
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 807
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 807
    Points : 13 503
    Points
    13 503
    Par défaut
    Citation Envoyé par Droïde Système7 Voir le message
    Juste avant le traitement
    Et juste après la fin du traitement
    Ce n'est pas clair ce que tu appelles avant et après traitement puisque que ce dernier est censé être dans la méthode Execute. Plus de code nous aiderait à comprendre.

    De plus le thread ne s'exécutera jamais (ou sporadiquement) si dans la même méthode (l'événement d'un bouton par exemple) tu enchaînes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    MyThread := TTestThread.Create(False);
    MyThread.Terminate;
    puisque la méthode Execute est conditionnée par Terminated et que la planification du thread par l'OS prend du temps.

  4. #4
    Membre chevronné
    Avatar de Droïde Système7
    Homme Profil pro
    Inscrit en
    Septembre 2003
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 2 276
    Points : 1 930
    Points
    1 930
    Par défaut
    Bonjour

    Oupsssss, merci les copains, j'avais déjà une fois tenté de chatouiller les Threads, mais j'avais reculé et m'étais sauvé en courant

    Stéphane, avec ce que tu me racontes, je confirme que j'ai de graves lacunes en ce domaine.

    Mais c'est plus facile de répondre à ceci :

    Combien de lignes dans la TStringList ? des millions ?
    Non non, des milliers à tout casser je pense.

    As-tu déjà une version mono-thread qui fonctionne, est-elle lente ?
    Imagine un projet basic de chez basic sans aucune complication en ce genre.

    Qu'elle est lien avec la fenêtre secondaire, une barre de progression ?
    Bin je ne souhaitais pas en parler pour ne pas encore plus compliquer la sauce ; mais en effet je pense (en rêve) à par exemple une petite fenêtre style "Veuillez patienter" ; mais encore mieux une petite fenêtre (boite surgissante) avec dedans les lignes (traitées ou non) défilant dans un Edit prouvant aux mirettes de l'utilisateur la continuité de fonctionnement (et non du plantage).

    Ainsi que souhaité par AndNotor ; je précise le topo afin d'éclaircir l'état des choses :

    Ce projet est des plus simple de chez simple : aucun Thread déjà ajouté ; ni BdD ; ni autre bidule compliqué.

    Au passage je précise également qu'au niveau StringList : cette dernière n'est pas triée sinon le résultat sera totalement erroné.

    En bref le but est de modifier certains tags du texte avec éventuellement un traitement précis ainsi que dito expliqué.

    En l'état et pour simplifier : imaginez une interface (Delphi7) toute bête avec aucun compo spéciaux.

    Un RichEdit et un bouton afin de lancer l'opération.

    Si je clic avec un texte à splitter chargé ; en gros ça fait environ une seconde d'attente par millier de lignes.

    Pour un certain poids/nombre de lignes ; ça passe assez rapidement même si faut attendre trois ou quatre secondes.

    Mais quand faut attendre plus d'une minute et voir l'interface se figer provisoirement ; c'est là que le problème rapplique !


    Voici en l'état ce que comporte en code la fiche secondaire spécialisé et inhérente au 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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    unit ThreadSplit;
     
    interface
     
    uses
      Classes;
      //Windows, Messages, SysUtils, Variants, Graphics, Controls, Forms,
      //Dialogs, StdCtrls, XPMan, ShellAPI, ComCtrls, Printers, StrUtils,
      //Shlobj, Menus, ExtCtrls, DateUtils, MMSystem;
     
    type
      TTestThread = class(TThread)
      procedure UpdateForm;
     
      private
        { Déclarations privées }
      protected
        procedure Execute; override;
      end;
     
    implementation
    uses
      Unit1;
     
    { 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 TTestThread.UpdateCaption;
        begin
          Form1.Caption := 'Mis à jour dans un thread';
        end; }
     
    { TTestThread }
     
    procedure TTestThread.Execute;
    begin
      { Placez le code du thread ici }
      //Edit1.
    end;
     
    procedure TTestThread.UpdateForm;
    begin
      //Application.Form1.Title:=Format("Progression : %d %%",[CurrentPercentDone]);
      //Form1.Caption := 'Mis à jour dans un thread';
    end;
     
     
    end.

    Pour ce qui est de ma Form principale comprenant le bouton et le RichEdit (pour faire simple), voici le principe de base :

    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
    Procedure...
    var
      // Theading box
      MyThread: TTestThread;
      ...
    begin
      ... 
      ...
      MyThread := TTestThread.Create(False);
      // Le thread est désormais créé, et actif.
      try
      begin
        Sleep(1);
        Patience.Show;
        ...
        // Démarrage...
        //  MyThread.Resume; (Oui je sais : ne pas taper)
        // Tu vois Stéphane : j'avais aussi pioché dans tes réponses sur un autre topic
        Patience.Refresh(); 
        Application.ProcessMessages();
        end;
        finally
      end;
      ...  
      ...
      // Démarrage AVANT TRAITEMENT SPLIT
      // MyThread.Resume; (Ne pas taper là aussi)
      ...
      StList := TStringList.create;
      ...
      try
        StList.LoadFromFile(OpenDlg.FileName);
        ...
        for i := 0 to StList.Count - 1 do
        begin  
          ...
          // Le traitement...
          ...
        end;
        Finally
        StList.free;
      end;      
      ...
      // Arrêt APRÈS TRAITEMENT SPLIT 
      // On demande au thread de s'arrêter "proprement". 
      MyThread.Terminate; 
      // Maintenant, on attend sa fermeture réelle. 
      ExitCode := MyThread.WaitFor;
      ...
    end; // Fin de cette procédure
    Voilà, vous pouvez voir que c'est du super simple de chez simple.

    Mon but est déjà de
    1 : d'éviter le "blocage" temporaire de fonctionnement
    2 : éventuellement bénéficier d'une fenêtre surgissante avertissant et mentionnant de patienter....

    Merci d'avoir eu le courage de lire jusque là ; mais je ne sais pas faire court

    Je sais bien évidemment que le code dito est incomplet voire lacunaire ; et justement c'est la raison à laquelle je suis ici parmi vous.

    Et j'ai bien l'impression que plus je me documente, et d'apprendre au niveau des Threads ; et plus je m'enfonce

  5. #5
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 807
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 807
    Points : 13 503
    Points
    13 503
    Par défaut
    Voilà une base de travail. On verra la suite en fonction de tes essais

    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
    type
      TTestThread = class(TThread)
      private
        FList :TStrings;
      protected
        procedure Execute; override;
      public
        property List :TStrings read FList write FList;
      end;
     
      TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        MyList :TStringList;
        MyThread :TTestThread;
        procedure ThreadTerminate(Sender :TObject);
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    {$R *.dfm}
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      Button1.Enabled := FALSE;
     
      MyList := TStringList.Create;
      MyList.LoadFromFile('...');
     
      MyThread := TTestThread.Create(TRUE);
      MyThread.List := MyList;
      MyThread.FreeOnTerminate := TRUE;
      MyThread.OnTerminate := ThreadTerminate;
      MyThread.Resume;
    end;
     
    procedure TForm1.ThreadTerminate(Sender: TObject);
    begin
      MyThread := nil;
     
      MyList.SaveToFile('...');
      MyList.Free;
     
      Button1.Enabled := TRUE;
    end;
     
    { TTestThread }
     
    procedure TTestThread.Execute;
    var
      i: integer;
    begin
      for i := 0 to FList.Count -1 do
      begin
        ...
      end;
    end;

  6. #6
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 649
    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 649
    Points : 25 397
    Points
    25 397
    Par défaut
    Si le scénario utilisateur c'est Clic -> Patience/Progression -> Résultat, pas besoin de thread
    D'ailleurs ton code, en fait, il n'y a pas de thread, il ne traite pas la liste
    Pire, le thread manipule une fenêtre de patience, à ne surtout pas faire !

    en fait ton code se résume à ceci, dans le traitement, tu gères l'affichage directement

    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
    Procedure...
      ...
    begin
      ...
      StList := TStringList.create;
      ...
      try
        StList.LoadFromFile(OpenDlg.FileName);
        ...
        ProgressBar1.Max := StList.Count-1;
        for i := 0 to StList.Count - 1 do
        begin  
          ...
          // Le traitement...
     
          // Affichage toutes les 200 lignes et "dé-freezage" de l'application toutes les 1000 lignes
          if I mod 200 = 0 then 
          begin
              ProgressBar1.Position := I;
              ProgressBar1.Refresh();
              if I mod 1000 = 0 then
                Application.ProcessMessages();
          end;
          ...
        end
      Finally
        StList.free;
      end;      
     
     
    end;
    ProgressBar1 c'est sur Form1
    Selon si cette procédure est dans Form1 ou ailleurs, tu peux passer ProgressBar1 en paramètre ou faire un CallBack (un Event c'est pareil)

    Si il y a un RichEdit dans l'affaire, BeginUpdate et EndUpdate

    J'ai justement un code qui lit un script maison, il le charge, colorise à la volée certains élements
    En particulier, le cas des lignes de plus 4Ko, le RichEdit fait plusieurs lignes même à WordWrap à False, ça pourrit mon script, l'ancien programme exécutait depuis le RichEdit, la nouvelle mouture utilise le script d'origine non altéré
    Sans BeginUpdate et EndUpdate, cela serait 100x plus lent !
    Et la progression est via un simple TLabeledEdit

    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 TScriptForm.LoadMemoFromStrings(AStrings: TStrings);
    var
      Chrono: System.Diagnostics.TStopwatch;
      I, CurrentLine, NewLine, NewLineCount, LoginLine, LogoutLine: Integer;
      Line, LinePrior: string;
      Caret, CaretPrior: Integer;
    begin
      Chrono := System.Diagnostics.TStopwatch.StartNew();
     
      pnlActions.Enabled := False;
      memoScript.ReadOnly := True;
      try
        memoScript.Lines.BeginUpdate();
        try
          memoScript.Lines.Clear();
     
          Caret := 0;
          CaretPrior := 0;
          CurrentLine := -1;
          LoginLine := -1;
          LogoutLine := -1;
          for I := 0 to AStrings.Count - 1 do
          begin
            Line := AStrings[I];
            if LoginLine < 0 then
              if StartsText('[Login]', Line) then
                LoginLine := I;
            if LogoutLine < 0 then
              if StartsText('[Logout]', Line) then
                LogoutLine := I;
     
            NewLine := -1;
            try
              NewLine := memoScript.Lines.Add(Line);
            except
              on E: EOutOfResources do // 'RichEdit line insertion error'
              begin
                memoScript.SelStart := Caret;
                memoScript.SelLength := Length(Line);
                memoScript.SelAttributes.Color := clMaroon;
                memoScript.SelLength := 0;
              end;
            end;
            // Attention, c'est sur la Ligne L que l'on détecte si la Ligne précédente a été découpée sur plusieurs lignes.
            if (NewLine >= 0) and (NewLine <> CurrentLine + 1) then
            begin
              NewLineCount := NewLine - CurrentLine;
              memoScript.SelStart := CaretPrior;
              memoScript.SelLength := Length(LinePrior);
              memoScript.SelAttributes.Color := clRed;
              memoScript.SelLength := 0;
            end;
     
            CaretPrior := Caret;
            Inc(Caret, Length(Line) + 1); // + 1 pour le Char CRLF
     
            CurrentLine := NewLine;
            LinePrior := Line;
     
            if not ByteBool(I) then
            begin
              edScriptFileName.EditLabel.Caption := Format('Script file : %d Lines load in %d ms, waiting ...', [memoScript.Lines.Count, Chrono.ElapsedMilliseconds]);
              Application.ProcessMessages();
            end;
          end;
     
          if LogoutLine >= 0 then
          begin
            // Recalage à cause des lignes trop longues
            LogoutLine := LogoutLine + memoScript.Lines.Count - AStrings.Count;
            for I := memoScript.Lines.Count - 1 downto LogoutLine + 1 do
            begin
              // Caret a été calculé ci-dessus durant le remplissage
              Line := memoScript.Lines[I];
              Dec(Caret, Length(Line) + 1); // + 1 pour le Char CRLF
              memoScript.SelStart := Caret;
              memoScript.SelLength := Length(Line);
              if memoScript.SelAttributes.Color <> clMaroon then
                memoScript.SelAttributes.Color := clWebOrange;
            end;
          end;
     
          if LoginLine >= 0 then
          begin
            Caret := 0;
            for I := 0 to LoginLine - 1 do
            begin
              Line := memoScript.Lines[I];
              memoScript.SelStart := Caret;
              memoScript.SelLength := Length(Line);
              if memoScript.SelAttributes.Color <> clMaroon then
                memoScript.SelAttributes.Color := clWebOrange;
              Inc(Caret, Length(Line) + 1); // + 1 pour le Char CRLF
            end;
          end;
        finally
          memoScript.Lines.EndUpdate();
        end;
     
        edScriptFileName.EditLabel.Caption := Format('Script file : %d Lines load in %d ms', [memoScript.Lines.Count, Chrono.ElapsedMilliseconds]);
        if memoScript.Lines.Count <> AStrings.Count then
          MessageDlg('Lignes de longueur excessive détectées', mtWarning, [mbOK], 0);
      finally
        memoScript.ReadOnly := False;
        pnlActions.Enabled := True;
      end;
    end;

    Pour quelques milliers de lignes, un Application.ProcessMessages toutes les 1000 itérations feraient aussi très bien le job
    L'astuce c'est justement de ne pas en abuser, le un Refresh du ProgressBar lui pouvant être à 200 itérations ...

    Le nombre d'itération pour la fréquence Patience/Progression, ça dépend du temps de traitement.


    A mon avis, avant le thread, c'est l'optimisation du traitement qu'il faut regarder.





    Et l'on n'a pas la réponse si tu veux avoir un seul thread qui manipule ou plusieurs simultanément.




    En complément de la réponse de AndNotOr

    MyThread ne doit pas manipuler après le Resume car avec FreeOnTerminate, il sera libéré tout seul (sa référence étant mis à nil au Terminate, moi je l'aurais même pas conservé)


    Pour la progression, tu peux faire en sorte de minimiser l'impact sur la performance

    dans le code ci-dessus, repris de AndNotOr, sans utiliser de Synchronize mais utilisant un Timer
    Le Timer affiche tous les 100 ms peut importe la vitesse du traitement, au pire 10 fois par seconde, largement suffisant

    tapé direct sur le forum donc coquille possible

    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
     
    type
      TTestThreadProgressEvent = procedure(Sender: TObject; Position: Integer; Max: Integer) of object;
     
      TTestThread = class(TThread)
      private
        FList :TStrings;
        FOnProgress: TTestThreadProgressEvent;
      protected
        procedure Execute; override;
      public
        property List :TStrings read FList write FList;
        property OnProgress: TTestThreadProgressEvent read FOnProgress write FOnProgress;
      end;
     
      TForm1 = class(TForm)
        Button1: TButton;
        Timer1: TTimer;
        ProgressBar1: TProgressBar;
        procedure Button1Click(Sender: TObject);
        procedure Timer1Timer(Sender: TObject);
      private
        MyList :TStringList;
        MyThread :TTestThread;
        FPosition: Integer; 
        FMax: Integer;
     
        procedure ThreadTerminate(Sender :TObject);
        procedure ThreadProgress(Sender: TObject; Position: Integer; Max: Integer);
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    {$R *.dfm}
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      Button1.Enabled := FALSE;
     
      MyList := TStringList.Create;
      MyList.LoadFromFile('...');
     
      ProgressBar1.Position := 0;
      ProgressBar1.Max := 100;
      ProgressBar1.Visible := True;
      Timer1Timer.Interval := 100;
      Timer1Timer.Enabled := True;
     
      MyThread := TTestThread.Create(TRUE);
      MyThread.List := MyList;
      MyThread.FreeOnTerminate := TRUE;
      MyThread.OnTerminate := ThreadTerminate;
      MyThread.OnProgress:= ThreadProgress;
      MyThread.Resume;
    end;
     
    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
      ProgressBar1.Position := FPosition;
      ProgressBar1.Max := FMax;
    end;
     
    procedure TForm1.ThreadTerminate(Sender: TObject);
    begin
      MyThread := nil;
     
      MyList.SaveToFile('...');
      MyList.Free;
     
      ProgressBar1.Visible := False;
      Timer1Timer.Enabled := False;
     
      Button1.Enabled := TRUE;
    end;
     
    procedure TForm1.ThreadProgress(Sender: TObject; Position: Integer; Max: Integer);
    begin
      FPosition := Position;
      FMax := Max;
    end;
     
    { TTestThread }
     
    procedure TTestThread.Execute;
    var
      i, LMax: integer;
    begin
      LMax := FList.Count - 1;
      for i := 0 to LMax do
      begin
        ...
        if Assigned(FOnProgress) then
          FOnProgress(Self, I, LMax);
     
      end;
    end;
    Et pour la progression - Version Synchronize
    A savoir que l'affichage c'est assez lent, plus on l'appel, plus c'est lent donc Astuce pour réduire les appels, l'exemple c'est tous les 256 lignes (via ByteBool c'est plus rapide qu'un modulo)


    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
     
    type
      TTestThreadProgressEvent = procedure(Sender: TObject; Position: Integer; Max: Integer) of object;
     
      TTestThread = class(TThread)
      private
        FList :TStrings;
        FOnProgress: TTestThreadProgressEvent;
      protected
        procedure Execute; override;
      public
        property List :TStrings read FList write FList;
        property OnProgress: TTestThreadProgressEvent read FOnProgress write FOnProgress;
      end;
     
      TForm1 = class(TForm)
        Button1: TButton;
        ProgressBar1: TProgressBar;
        procedure Button1Click(Sender: TObject);
      private
        MyList :TStringList;
        MyThread :TTestThread;
        FPosition: Integer; 
        FMax: Integer;
     
        procedure ThreadTerminate(Sender :TObject);
        procedure ThreadProgress(Sender: TObject; Position: Integer; Max: Integer);
        procedure ThreadProgressSync();
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    {$R *.dfm}
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      Button1.Enabled := FALSE;
     
      MyList := TStringList.Create;
      MyList.LoadFromFile('...');
     
      ProgressBar1.Position := 0;
      ProgressBar1.Max := 100;
      ProgressBar1.Visible := True;
     
      MyThread := TTestThread.Create(TRUE);
      MyThread.List := MyList;
      MyThread.FreeOnTerminate := TRUE;
      MyThread.OnTerminate := ThreadTerminate;
      MyThread.OnProgress:= ThreadProgress;
      MyThread.Resume;
    end;
     
    procedure TForm1.ThreadTerminate(Sender: TObject);
    begin
      MyThread := nil;
     
      MyList.SaveToFile('...');
      MyList.Free;
     
      ProgressBar1.Visible := False;
     
      Button1.Enabled := TRUE;
    end;
     
     
    procedure TForm1.ThreadProgress(Sender: TObject; Position: Integer; Max: Integer);
    begin
      FPosition := Position;
      FMax := Max;
      if not ByteBool(Position) or (Position = Max) then
        Synchronize(ThreadProgressSync);
    end;
     
     
    procedure ThreadProgressSync();
    begin
      ProgressBar1.Position := FPosition;
      ProgressBar1.Max := FMax;
    end;
     
    { TTestThread }
     
    procedure TTestThread.Execute;
    var
      i, LMax: integer;
    begin
      LMax := FList.Count - 1;
      for i := 0 to LMax do
      begin
        ...
        if Assigned(FOnProgress) then
          FOnProgress(Self, I, LMax);
     
      end;
    end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  7. #7
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 807
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 807
    Points : 13 503
    Points
    13 503
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    MyThread ne doit pas manipuler après le Resume car avec FreeOnTerminate, il sera libéré tout seul (sa référence étant mis à nil au Terminate, moi je l'aurais même pas conservé)
    Si on peut mais évidemment en testant d'abord son assignation. Ce n'est pas le but de lire des propriétés (quoique) mais suffisant pour un Terminate.

    La libération d'un TThread est souvent problématique (quand le faire). Ici on s'arrange pour finaliser dans OnTerminate et ne pas s'en occupe. En attendant MyThread est parfaitement utilisable.

    Il reste aussi le bon vieux PostMessage, suffisant pour une barre de progression.

  8. #8
    Membre chevronné
    Avatar de Droïde Système7
    Homme Profil pro
    Inscrit en
    Septembre 2003
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 2 276
    Points : 1 930
    Points
    1 930
    Par défaut
    Whouaaaahhh merci les copains ; là j'ai du taf à tester avec bonheur !

    Je vais prendre le temps de tout bien vous lire calmement et éplucher (si je peux ) et ensuite tester.

    Je vous donnerai le résultat de tout ça bientôt

    Aller, je vais au taf !

  9. #9
    Membre chevronné
    Avatar de Droïde Système7
    Homme Profil pro
    Inscrit en
    Septembre 2003
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 2 276
    Points : 1 930
    Points
    1 930
    Par défaut Petit à petit...
    Suite des courses :

    Stéphane disait :
    A mon avis, avant le thread, c'est l'optimisation du traitement qu'il faut regarder.
    Pour l'instant en effet, je ne m'éparpille pas et suis à 100% sur cette optimisation (Ensuite on verra le Thread).

    Déjà à ce point, à l'aide d'un seul Application.ProcessMessages() bien placé (dans une fonction appelée en boucles), m'a littéralement scotché devant le no freeze : je n'y croyais pas

    Quant à la paire ...Lines...Update(), hé bien ça n'a rien donné du tout ; au contraire même ça me fichait une sorte de scintillement. J'ai pourtant tenté de la placer en tests à divers endroits.

    Le principal est déjà la victoire sur ce freezage

    Merci les copains : je continue mes essais en pensant à vous

    (Désolé, je ne me souviens plus comment surligner en gris certains mots de code en lignes de texte, par exemple Application.ProcessMessages()
    J'ai pourtant scruté la barre d'outils avec attention.
    Dites-moi quelle paire de balises, je le noterai)



    ÉDIT : Whouaaaahhh, grâce au code à Stéphane : j'ai réussi à ajouter une superbe ProgressBar

    @ +

  10. #10
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 752
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 752
    Points : 5 457
    Points
    5 457
    Par défaut
    Citation Envoyé par Droïde Système7 Voir le message
    (Désolé, je ne me souviens plus comment surligner en gris certains mots de code en lignes de texte, par exemple Application.ProcessMessages()
    J'ai pourtant scruté la barre d'outils avec attention.
    Dites-moi quelle paire de balises, je le noterai)
    Avec C et /C (avec les crochets bien sûr).
    Comme ceci : Application.ProcessMessages().

  11. #11
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 649
    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 649
    Points : 25 397
    Points
    25 397
    Par défaut
    BeginUpdate et EndUpdateajoute les au tout début et tout fin dans l'ensemble du traitement soit avant et après la boucle.


    Pour le fonctionnement voir dans cette section à afficher :

    Le code du texte ci-dessus
    [c]BeginUpdate[/c] et [c]EndUpdate [/c]ajoute les au tout début et tout fin dans l'ensemble du traitement soit avant et après la boucle.
    tu peux aussi utiliser codeinline.

    tu peux aussi utiliser [codeinline]codeinline[/codeinline].
    Et pour afficher du code du forum sans qu'il soit interpréter c'est noparse :

    [noparse]
    tu peux aussi utiliser [codeinline]codeinline[/codeinline].
    [/noparse]
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  12. #12
    Membre chevronné
    Avatar de Droïde Système7
    Homme Profil pro
    Inscrit en
    Septembre 2003
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 2 276
    Points : 1 930
    Points
    1 930
    Par défaut
    Merci les copains Popo et Stéphane : j'ai placé ces indications dans SoftNote

    Je pense que ça devrait également servir à d'autres développeurs.

    Stéphane : j'avais tout bien ratissé mais je vais retester encore avec le BeginUpdate/EndUpdate.
    Et pourtant, j'en ai testé des configurations Mais je suis du genre à ne pas lâcher le morceau aussi vite ; et vais revoir ma copie, merci à notre ami GetTickCount.

    Tu avais raison : cette optimisation devrait me suffire sans avoir recours à Threader quoi que ce soit
    Quel bonheur de contempler aucun freezage au cours d'un spiltage même long puisque la barre de progression semble parler à l'oreille pour rassurer : "Patiente mon pote : ça va le faire"

    Ceci dit et malgré tout, je suis loin d'oublier de souhaiter mener à bien cette manip de Threadage complet afin d'obtenir enfin un exemple fonctionnel... Andnotor je n'oublie pas

    @+


    ÉDIT : Stéphane, je viens encore grâce à ton aide d'améliorer les performances sur une liste d'environ 15 000 lignes !
    En disposant le couple (unique) BeginUpdate/EndUpdate au dessus de la boucle principale/première et tout au dessous du code de la procédure hors boucle bien sûr.
    De 32 secondes c'est passé à 24 secondes

  13. #13
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 649
    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 649
    Points : 25 397
    Points
    25 397
    Par défaut
    De rien, ne pas oublier le try finally pour le BeginUpdate try ... finally EndUpdate, on ne sait jamais quand se produit une erreur.


    Par curiosité, si tu modifie QUE le texte et non pas d'attributs de style, couleur ... il y a peut-être un moyen pour que cela soit plus rapide

    Clones le contenu du RichEdit, tu exportes StringList.Assign(RichEdit.Lines), tu traites en local la StringList, et tu importes via RichEdit.Lines.Assign(StringList).
    D'ailleurs le clonage sera plus rapide via un Stream la séquence étant RichEdit.Lines.SaveToStream; Seek Beginning; StringList.LoadFromStream et la réciproque StringList.SaveToStream; Seek Beginning; RichEdit.Lines.LoadFromStream mais la propriété PlainText influence cette phase.


    Car je pense que la TStringList est plus rapide que la TRichEditStrings si tu as beaucoup de manipulation
    Maintenant il faut espérer que le gain de temps sur le traitement n'est pas "consommé" par l'export/import.

    Par contre, si tu modifie les Attributs de Style, tu ne pourras pas améliorer grand chose.
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  14. #14
    Membre chevronné
    Avatar de Droïde Système7
    Homme Profil pro
    Inscrit en
    Septembre 2003
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 2 276
    Points : 1 930
    Points
    1 930
    Par défaut
    Stéphane, tu me files encore du taf

    Oui, je vais approfondir aussi par là.

    Au niveau de la gestion des couleurs, en effet c'est ça qui dévore le plus de temps.

    Mais je vais déjà me jeter sur la protection try finally du code en question.

    Merci @ +

  15. #15
    Membre chevronné
    Avatar de Droïde Système7
    Homme Profil pro
    Inscrit en
    Septembre 2003
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 2 276
    Points : 1 930
    Points
    1 930
    Par défaut
    Bonjour

    Stéphane, tu suggérais également pour améliorer les performances ceci :

    D'ailleurs le clonage sera plus rapide via un Stream la séquence étant RichEdit.Lines.SaveToStream; Seek Beginning; StringList.LoadFromStream et la réciproque StringList.SaveToStream; Seek Beginning; RichEdit.Lines.LoadFromStream mais la propriété PlainText influence cette phase.
    Question conne : qu'appelles-tu clonage ? Ou autrement dit le clonage de quoi ?

    S'il s'agit du "chargement" du fichier texte vers le RichEdit ; c'est instantané ou presque.
    Idem d'un "save" du RichEdit vers un fichier texte.


    Ceci dit en passant, au début en CdC, je pensais que les fichiers à traiter ne devaient pas trop comporter de lignes.

    Un utilisateur m'annonce qu'il vient de tester un fichier de 1 200 000 lignes, et qu'une heure ensuite, la ProgresssBar n'est qu'à 20% d'avancement

    Au début ça ne devait pas excéder quelques milliers de lignes.

    Ceci dit, je vais lui faire confirmer qu'au moins ça ne plante ni freeze ; si c'est OK de ce côté, au moins ce sera déjà très appréciable

  16. #16
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 649
    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 649
    Points : 25 397
    Points
    25 397
    Par défaut
    Clone juste synonyme d'une copie !
    C'était le principe du SaveToStream\LoadFromStream
    Oui le LoadFromFile utilise un mode passant par l'API Windows, c'est TOUT le texte qui est modifié, c'est beaucoup plus rapide que l'accès ligne par ligne.

    L'idée c'était uniquement pour modifier le texte mais si tu modifies les couleurs c'est plus délicat

    Cependant, avec 1 200 000 lignes, vouloir tout afficher dans un RichEdit n'est pas une bonne idée
    Et puis aucun humain ne peut lire autant de lignes, cela ne servira à rien

    Tu devrais travailler sur une version mémoire du fichier dans la TStringList, en parallèle tu crèes un autre fichier qui te donne les infos du traitement, position (ligne / colonne), longueur, info diverses.
    Ainsi tu stockes le résultat du traitement, l'utilisateur pourra revenir sur le résultat autant de fois qu'il le souhaite, avantage, tu lances cela la nuit, ainsi le matin, l'opérateur a le résultat.

    Ensuit tu affiches dans le RichEdit uniquement 1000 lignes avec un système de pagination pour naviguer dans le fichier, grâce au fichier secondaire, tu as tout ce qu'il faut pour créer un affichage dynamique.


    Tu pourrais même utiliser directement le Stream, plus rapide encore mais cela nécessite de calculer soit même la position (ligne / colonne)
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  17. #17
    Membre chevronné
    Avatar de Droïde Système7
    Homme Profil pro
    Inscrit en
    Septembre 2003
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 2 276
    Points : 1 930
    Points
    1 930
    Par défaut
    Stéphane

    Ah le clonage, oki là oui je pige mieux.

    Cependant, avec 1 200 000 lignes, vouloir tout afficher dans un RichEdit n'est pas une bonne idée
    Et oui tu as raison sur le but d'affichage en RichEdit qui est un facteur important de ralentissement.

    Je vais voir si sans affichage...

    Mais ce matin je viens d'avoir le commentaire d'un utilisateur passant idem ces 1 200 000 lignes via du VBA en 3 secondes seulement
    (Sans affichage hein, seulement l'enregistrement du fichier traité)

    Là, je me pose sérieusement des questions.

    Même si par exemple je splittais (passé X lines) en 10 blocs threadés de 100 000 lignes à traiter, et qu'ensuite je reconstituais tout cela convenablement ; je doute que cette manip optimisée (?) atteigne la performance des 3 secondes.

    Arrivé à ce point je ne sais plus trop ; si la roue est déjà inventée et fonctionnelle, pas à moi de la réinventer.

    Mais toute discussion est intéressante et instructive à assimiler et mémoriser



    ÉDIT : après recul, je vais tester tout très simplement et sans affichage.
    Voir déjà si je suis fichu de transposer le code de cette appli, en algo hyper simple :

    Load et traitement dans StringList --> save directo txt.

    Bien entendu si c'est encourageant je vais optimiser, mais chaque chose en son temps

  18. #18
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 807
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 807
    Points : 13 503
    Points
    13 503
    Par défaut
    Tu n'as pas un exemple de ce que tu dois réaliser ?
    Je suis un peu dans le vague....

  19. #19
    Membre chevronné
    Avatar de Droïde Système7
    Homme Profil pro
    Inscrit en
    Septembre 2003
    Messages
    2 276
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 2 276
    Points : 1 930
    Points
    1 930
    Par défaut
    Andnotor, oui tu as raison, mais je crois qu'en virant tout rapport avec un ou des StringLists ; ça devrait accélérer un max.

    En plus j'aime mieux, à moins de patiner des heures et des heures ; me débrouiller tout seul : comme ça que l'on apprend le mieux.

    J'avance, mais ça plante aussi

    De toute façon je redonne toujours des nouvelles.

    Merci



    ÉDITH : ça y est y suis arrivé sans aucune fioriture niveau interface.

    Sur un simple texte de 24 000 000 lignes, d'un poids de 22,90 Mo ça donne 16 secondes !!!

    Et encore : je n'utilise que des StingLists tous bêtes.

  20. #20
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 649
    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 649
    Points : 25 397
    Points
    25 397
    Par défaut
    Si c'est que traitement de texte, il y a peut-être des choses à améliorer.
    Surtout si VBA fait mieux.
    D7 sans FastMM faut éviter des boucles genre S := S +C, la concaténation étant assez lente surtout sur des millions de fois.

    Franchement, je pense que l'on pourrait t'aider à optimiser ton code sauf si tu ne peux pas fournir celui-ci même si je ne vois pas ce que l'on ferait d'un traitement de fichier inconnu.

    Avant de songer au thread, il faut cuisiner à fond ton code, en D7 le passage en PChar faisait des miracles mais faut être habitué à cette façon de coder à coup de pointer.

    Un détail, si tu as appels de fonction genre Split(S: string) passe les en Split(const S: string), si c'est appelé 24M de fois, ça fera un gain de temps. les variables String locales n'ont pas de compteur de référence, const passe le pointeur, en D7, cela évite une allocation, c'est radical, avec FastMM l'effet est nettement moins significatif.

    Tu n'imagines pas ce que l'on peut trouver comme ligne anodine mais très lente.
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

Discussions similaires

  1. [Thread] Comment faire fonctionner QThread?
    Par Elv13 dans le forum Multithreading
    Réponses: 1
    Dernier message: 07/05/2008, 15h49
  2. Threading : mon abort ne fonctionne pas :(
    Par Amokrane dans le forum C#
    Réponses: 4
    Dernier message: 04/05/2008, 14h04
  3. Croisements de threads / Fonctionnement des "delegate"
    Par Fabllot dans le forum C++/CLI
    Réponses: 3
    Dernier message: 18/07/2007, 12h18
  4. fonctionnent de la méthode run dans les threads
    Par L4BiN dans le forum Concurrence et multi-thread
    Réponses: 8
    Dernier message: 25/07/2006, 11h06
  5. [Applet+Threads] Pause et resume qui fonctionne pas
    Par MinsK dans le forum Concurrence et multi-thread
    Réponses: 4
    Dernier message: 29/11/2005, 18h39

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