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

Lazarus Pascal Discussion :

Control.Update (ou .Repaint) moins efficace que Application.ProcessMessages [Lazarus]


Sujet :

Lazarus Pascal

  1. #1
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 719
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut Control.Update (ou .Repaint) moins efficace que Application.ProcessMessages
    Bonsoir,

    Je ne sais pas si c'est un bug lié à Linux, mais je constate un comportement bizarre ou, à tout le moins, pas en accord avec l'aide.

    Je loggue des événements dans un Tmemo et, pour avoir toujours la dernière ligne visible, j'ai monté ma procédure de log ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    procedure TForm1.log(s: string; ShowTime: boolean);
    begin
      if ShowTime then s := TimeToStr(Now) + ' ' + s;
      mmoLog.Lines.Append(s);
      mmoLog.SelStart := length(mmoLog.Text); // pour positionner le curseur à la fin du mémo
      Application.ProcessMessages;
    end;
    Ça fonctionne bien mais je trouvais que App.ProcMess c'était un peu prendre une enclume pour écraser une mouche, d'autant plus que l'aide me dit, pour Update :
    Redraw invalidated parts of the control immediately.
    et pour Repaint :
    Immediate redraw of the control, bypassing the message queue.
    À la lecture de ces deux lignes on pourrait se dire que ça va le faire, mais si je remplace App.ProcMess par mmoLog.Repaint ou par .Update, hé bien le mémo n'est plus "scrollé" jusqu'en bas et les dernières lignes ne sont plus visibles.

    Une idée, quelqu'un ?
    Contexte : Debian 7 32 bits et mon vieux Lazarus 1.4 / FPC 2.6.2 (mais pour ce que j'en fais ça suffit amplement)

    EDIT :
    Ah, pour ceux qui voudraient faire des tests, une fiche avec 3 boutons, 3 petits memos (avec scrollbar verticale), un timer (interval à 1000) et en avant :

    Nom : formtest.jpg
Affichages : 660
Taille : 24,9 Ko
    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
      private
        { private declarations }
        procedure log1(s: string; ShowTime: boolean);
        procedure log2(s: string; ShowTime: boolean);
        procedure log3(s: string; ShowTime: boolean);
      public
        { public declarations }
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    {$R *.lfm}
     
    procedure TForm1.log1(s: string; ShowTime: boolean);
    begin
      if ShowTime then s := TimeToStr(Now) + ' ' + s;
      mmoLog1.Lines.Append(s);
      mmoLog1.SelStart := length(mmoLog1.Text);
      mmoLog1.Repaint;
    //  mmoLog1.Update;
    //  Application.ProcessMessages;
    end;
     
    procedure TForm1.log2(s: string; ShowTime: boolean);
    begin
      if ShowTime then s := TimeToStr(Now) + ' ' + s;
      mmoLog2.Lines.Append(s);
      mmoLog2.SelStart := length(mmoLog2.Text);
    //  mmoLog2.Repaint;
      mmoLog2.Update;
    //  Application.ProcessMessages;
    end;
     
    procedure TForm1.log3(s: string; ShowTime: boolean);
    begin
      if ShowTime then s := TimeToStr(Now) + ' ' + s;
      mmoLog3.Lines.Append(s);
      mmoLog3.SelStart := length(mmoLog3.Text);
    //  mmoLog3.Repaint;
    //  mmoLog3.Update;
      Application.ProcessMessages;
    end;
     
    procedure tempo;
    var
      k,t: integer;
    begin
      k := 0; // happy compilo
      for t := 0 to 100000000 do k := k + t; // tempo pour "voir"
    end;
     
    procedure TForm1.Button1Click(Sender: TObject);
    var
      i : integer;
    begin
      for i := 0 to 20 do begin tempo; log1(IntToStr(i), True); end;
    end;
     
    procedure TForm1.Button2Click(Sender: TObject);
    var
      i : integer;
    begin
      for i := 0 to 20 do begin tempo; log2(IntToStr(i), True); end;
    end;
     
    procedure TForm1.Button3Click(Sender: TObject);
    var
      i : integer;
    begin
      for i := 0 to 20 do begin tempo; log3(IntToStr(i), True); end;
    end;
     
    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
      Application.ProcessMessages;
      // pour la prise en compte du bouton d'arrêt dans real prog
    end;
    Et avec ça on constate que Repaint et/ou Update fonctionnent très mal, enfin, pas comme on pourrait s'y attendre, à comparer avec App.ProcMess...
    Merci de prendre le temps de jeter un œil.
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  2. #2
    Responsable Lazarus & Pascal

    Avatar de gvasseur58
    Homme Profil pro
    Cultivateur de code (bio)
    Inscrit en
    Février 2013
    Messages
    1 436
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Cultivateur de code (bio)
    Secteur : Enseignement

    Informations forums :
    Inscription : Février 2013
    Messages : 1 436
    Points : 20 855
    Points
    20 855
    Billets dans le blog
    84
    Par défaut
    Citation Envoyé par Jipété Voir le message
    Je loggue des événements dans un Tmemo et, pour avoir toujours la dernière ligne visible, j'ai monté ma procédure de log ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    procedure TForm1.log(s: string; ShowTime: boolean);
    begin
      if ShowTime then s := TimeToStr(Now) + ' ' + s;
      mmoLog.Lines.Append(s);
      mmoLog.SelStart := length(mmoLog.Text); // pour positionner le curseur à la fin du mémo
      Application.ProcessMessages;
    end;
    Bonsoir,

    Je suis un peu surpris, car avec Windows, il n'est nul besoin de repositionner le curseur : il y va tout seul, sans SelStart et encore moins de ProcessMessages .

    Pour redessiner, la méthode à utiliser prioritairement est Invalidate : elle évite les scintillements. Je n'ai pas été farfouillé dans le code source, mais certains prétendent que Refresh, Repaint et Update sont équivalents avec Lazarus.

    Je vais encore être obligé de réactiver mon Linux, mais ce n'est pas plus mal .

    Cordialement,

    Gilles
    Accès à mon site et à mon blog. Actualités, cours et ressources Delphi, Lazarus et Pascal.
    Pensez à la balise - Quelqu'un vous a aidé ou vous appréciez une intervention ? Pensez au

  3. #3
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 719
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Bonsoir Gilles,
    Citation Envoyé par gvasseur58 Voir le message
    Pour redessiner, la méthode à utiliser prioritairement est Invalidate : elle évite les scintillements. Je n'ai pas été farfouillé dans le code source, mais certains prétendent que Refresh, Repaint et Update sont équivalents avec Lazarus.
    L'aide de Invalidate :
    Force a delayed Repaint of the control, by marking its visible area of the control as invalid.
    Je ne vois pas trop de différence entre forcer un "delayed repaint" et appeler quand je veux un "repaint" tout court.
    Et effectivement, en termes de résultat dans le mémo, c'est encore plus catastrophique que Repaint ou Update : le résultat n'est affiché qu'à la fin de la boucle !

    PS : pas noté dans mon post précédent mais j'avais aussi essayé Refresh sans plus de résultat

    Citation Envoyé par gvasseur58 Voir le message
    Je suis un peu surpris, car avec Windows, il n'est nul besoin de repositionner le curseur : il y va tout seul, sans SelStart et encore moins de ProcessMessages .
    Alors là je suis surpris, car venant de Delphi sous Windows, c'est une des premières choses que j'ai apprises : un ProcessMessages dans la boucle pour voir l'avancement des choses et éviter de bloquer la fenêtre par la même occasion.

    EDIT :
    Alors effectivement, je viens de tester avec ma version 1.6rc1 sous XP et c'est donc bien un bug sous Linux ! J'en ai maaaaaaaaaaaaaaaaaaaaaaaarre

    Sous Windows, pas besoin de SelStart pour positionner le mémo sur la dernière ligne, en effet.
    Par contre il faut quand même ProcMess, et n'essayez pas de travailler avec les trois mémos en même temps, malgré ProcMess dans chaque proc d'affichage : 1 mémo affiche et les autres sont bloqués, même avec 4 ProcMess : 1 par procédure d'affichage et 1 autre dans la proc du timer !
    C'est nuuuuuuuuul !
    Multi-tâches ces machines et ces OS ? Dans leurs rêves, oui...

    Et je voudrais bien savoir comment font ceux qui font des IHM pour des décors de films où on voit des compteurs bouger dans tous les coins.

    EDIT2 : l'affichage final n'est pas le même selon que j'utilise Invalidate (=correct) ou Update (manque la dernière ligne) : les mecs, on n'est pas rendu sous Linux...
    Nom : invalidate_update.png
Affichages : 622
Taille : 38,7 Ko
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  4. #4
    Expert éminent
    Avatar de jurassic pork
    Homme Profil pro
    Bidouilleur
    Inscrit en
    Décembre 2008
    Messages
    3 947
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 3 947
    Points : 9 275
    Points
    9 275
    Par défaut
    hello,
    dans l'exemple (sertest) de mon composant TLazserial, voici comment je procède pour afficher dans un Tmemo ce qui arrive sur la ligne série, pour garder aussi la dernière ligne visible :

    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
    procedure TFMain.SerialRxData(Sender: TObject);
    var Str : string;
    begin
      Str :=  Serial.ReadData;
      CurPos := Pos( Char(10) ,Str);
      if CurPos = 0 then begin
        FTempStr := FTempStr + Str;
      end
      else begin
        FTempStr := FTempStr + Copy( Str, 1, CurPos-1);
        Memo.Lines.BeginUpdate;
        Memo.Lines.Add(FtempStr);
         Memo.Lines.EndUpdate;
        Memo.SelStart := Length(Memo.Lines.Text)-1;
        Memo.SelLength:=0;
        AnalyseTrames(FtempStr);
        FTempStr := Copy(Str,CurPos +1, Length(Str) - CurPos);
      end;
     
    end;
    la difficulté supplémentaire dans mon code c'est que parfois je ne reçois pas une ligne entière (terminée par un RC) et donc je dois gérer en plus la position curseur et passer par un buffer intermédiaire.
    Mon code fonctionne sous windows et linux.

    Ami calmant J.P (pas té)
    Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

  5. #5
    Responsable Lazarus & Pascal

    Avatar de gvasseur58
    Homme Profil pro
    Cultivateur de code (bio)
    Inscrit en
    Février 2013
    Messages
    1 436
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Cultivateur de code (bio)
    Secteur : Enseignement

    Informations forums :
    Inscription : Février 2013
    Messages : 1 436
    Points : 20 855
    Points
    20 855
    Billets dans le blog
    84
    Par défaut
    Citation Envoyé par Jipété Voir le message
    Je ne vois pas trop de différence entre forcer un "delayed repaint" et appeler quand je veux un "repaint" tout court.
    Et effectivement, en termes de résultat dans le mémo, c'est encore plus catastrophique que Repaint ou Update : le résultat n'est affiché qu'à la fin de la boucle !
    La différence est due au fait que l'OS garde la main et rafraîchit quand c'est opportun (c'est pourquoi il n'y a pas de scintillement). On peut sans doute aussi expliquer ainsi la différence entre Invalidate et Update constatée plus loin, sans compter que Update n'invalide pas le contrôle, mais oblige simplement à repeindre les régions qui ont déjà été invalidées.

    Citation Envoyé par Jipété Voir le message
    PS : pas noté dans mon post précédent mais j'avais aussi essayé Refresh sans plus de résultat
    Là, Refresh et Repaint sont équivalents, la première appelant la seconde (heureusement que tu n'obtenais pas un autre résultat ).

    Citation Envoyé par Jipété Voir le message
    Alors là je suis surpris, car venant de Delphi sous Windows, c'est une des premières choses que j'ai apprises : un ProcessMessages dans la boucle pour voir l'avancement des choses et éviter de bloquer la fenêtre par la même occasion.
    Avec ProcessMessages, tu permets en effet de traiter les événements. Cependant, de nombreux programmeurs évitent son emploi qui dévoile souvent la mauvaise conception d'un programme. Le mieux est que le composant/ l'élément traite le problème en interne et c'est visiblement ce que fait soit Lazarus soit Windows (je n'ai pas été vérifié qui fait quoi).

    Citation Envoyé par Jipété Voir le message
    EDIT :
    Alors effectivement, je viens de tester avec ma version 1.6rc1 sous XP et c'est donc bien un bug sous Linux ! J'en ai maaaaaaaaaaaaaaaaaaaaaaaarre
    Cher Jipété, je ne vais te plaindre : depuis le temps que je te suggérais de passer à une version plus récente de Lazarus . Certains reprochent à ce dernier d'avancer lentement, mais il avance et je te certifie que la version 1.6 a corrigé de nombreux problèmes (oui, je sais, sauf un qui te tient vraiment à cœur ). Et pourquoi tester avec 1.6rc1 ?

    Citation Envoyé par Jipété Voir le message
    Sous Windows, pas besoin de SelStart pour positionner le mémo sur la dernière ligne, en effet.
    Par contre il faut quand même ProcMess
    Oui pour la première affirmation ; peut-être pour la seconde. Pour le traitement lui-même ProcessMessages est inutile (pour reprendre la main ?).

    Citation Envoyé par Jipété Voir le message
    , et n'essayez pas de travailler avec les trois mémos en même temps, malgré ProcMess dans chaque proc d'affichage : 1 mémo affiche et les autres sont bloqués, même avec 4 ProcMess : 1 par procédure d'affichage et 1 autre dans la proc du timer !
    C'est nuuuuuuuuul !
    Multi-tâches ces machines et ces OS ? Dans leurs rêves, oui...
    Si tu veux du multitâche, il faut utiliser les threads pour que chaque processus ait son petit univers douillet et indépendant...

    Cordialement,

    Gilles
    Accès à mon site et à mon blog. Actualités, cours et ressources Delphi, Lazarus et Pascal.
    Pensez à la balise - Quelqu'un vous a aidé ou vous appréciez une intervention ? Pensez au

  6. #6
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 719
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Citation Envoyé par gvasseur58 Voir le message
    Avec ProcessMessages, tu permets en effet de traiter les événements. Cependant, de nombreux programmeurs évitent son emploi qui dévoile souvent la mauvaise conception d'un programme.
    Mauvaise conception ? Je veux bien un exemple d'une bonne conception prenant en compte le point ci-dessous :


    Citation Envoyé par gvasseur58 Voir le message
    Pour le traitement lui-même ProcessMessages est inutile (pour reprendre la main ?).
    Yes, pour reprendre la main, pour éviter que l'IHM ait l'air d'être plantée, pour pouvoir la déplacer pendant que le mémo s'incrémente, pour pouvoir cliquer sur un bouton "Stop", etc.


    Citation Envoyé par gvasseur58 Voir le message
    Et pourquoi tester avec 1.6rc1 ?
    Parce que c'est ce qui était dispo quand j'ai créé la machine virtuelle concernée, et grosse flemme de migrer, n'ayant rien lu d'intéressant pour moi dans les release notes.
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  7. #7
    Responsable Lazarus & Pascal

    Avatar de gvasseur58
    Homme Profil pro
    Cultivateur de code (bio)
    Inscrit en
    Février 2013
    Messages
    1 436
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Cultivateur de code (bio)
    Secteur : Enseignement

    Informations forums :
    Inscription : Février 2013
    Messages : 1 436
    Points : 20 855
    Points
    20 855
    Billets dans le blog
    84
    Par défaut
    Citation Envoyé par Jipété Voir le message
    Mauvaise comception ?
    Je te renvoie à deux articles (parmi d'autres et en anglais) qui indiquent deux mauvaises façons d'utiliser ProcessMessages (à côté de moins pires et de bonnes ) : ici et . Encore un qui est posté chez nous, mais en anglais once again : ici.
    C'est à propos de Delphi, mais applicable à Lazarus.

    Une fois que tu as repéré les dangers possibles de ProcessMessages (entre autres de réentrance, de désynchronisation et de ralentissement du programme), tu peux rechercher si nécessaire une meilleure méthode : en général, celle adoptée est le multi-threads qui libère le processus principal de telle sorte qu'il puisse toujours répondre aux clics sur les boutons par exemple. C'est en ce sens que l'utilisation de ProcessMessages est souvent le signe d'une mauvaise conception : elle règle un problème, mais en négligeant ceux qu'elle crée .

    Maintenant, de temps en temps, pour se sortir rapidement d'une situation délicate, pourquoi se gêner ?
    Accès à mon site et à mon blog. Actualités, cours et ressources Delphi, Lazarus et Pascal.
    Pensez à la balise - Quelqu'un vous a aidé ou vous appréciez une intervention ? Pensez au

  8. #8
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 719
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Yop !

    Merci pour les liens, ça m'a rappelé le bon vieux temps de Delphi (car, oui, l'article de Piette je le connaissais déjà )
    Citation Envoyé par gvasseur58 Voir le message
    Une fois que tu as repéré les dangers possibles de ProcessMessages (entre autres de réentrance, de désynchronisation et de ralentissement du programme), tu peux rechercher si nécessaire une meilleure méthode : en général, celle adoptée est le multi-threads qui libère le processus principal de telle sorte qu'il puisse toujours répondre aux clics sur les boutons par exemple.
    Oui, mais dans mon cas (faire afficher la fin du mémo pour pouvoir lire la dernière ligne arrivée), ça n'est plus l'enclume pour écraser la mouche, c'est carrément le rouleau-compresseur !

    Citation Envoyé par gvasseur58 Voir le message
    Maintenant, de temps en temps, pour se sortir rapidement d'une situation délicate, pourquoi se gêner ?
    Et je crois bien que je vais rester avec cette option, puisque ces noms alléchants comme Repaint, Update, etc. ne sont pas opérationnels comme attendu, sous Linux...
    Bah, on va en rester là.
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  9. #9
    Expert éminent
    Avatar de jurassic pork
    Homme Profil pro
    Bidouilleur
    Inscrit en
    Décembre 2008
    Messages
    3 947
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 3 947
    Points : 9 275
    Points
    9 275
    Par défaut
    hello,
    mauvaise conception ?
    Jipété je viens d'essayer ton code sous Ubuntu 14.04 : ta procédure tempo avec sa boucle infernale ne laisse pas le temps au programme de "respirer" et doit consommer un maximum de CPU. La petite instruction de log qui se glisse juste après n'a pas le temps d'afficher car les messages d'affichage doivent être bloqués par la procédure tempo qui reprend de plus belle.
    En faisant comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    procedure TForm1.Button2Click(Sender: TObject);
    var
      i : integer;
    begin
      for i := 0 to 20 do begin tempo;
        log2(IntToStr(i), True);
       Application.ProcessMessages;
      end;
    end;
    il n' y a plus le problème.
    Mais c'est la procédure tempo qui est en cause.

    Ami calmant, J.P (pas té)
    Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

  10. #10
    Expert éminent
    Avatar de jurassic pork
    Homme Profil pro
    Bidouilleur
    Inscrit en
    Décembre 2008
    Messages
    3 947
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 3 947
    Points : 9 275
    Points
    9 275
    Par défaut
    Cela se passe beaucoup mieux si l'on remplace ta procédure tempo par un timer :
    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
      private
    // ...
        { private declarations }
        procedure log1(s: string; ShowTime: boolean);
        procedure log2(s: string; ShowTime: boolean);
        procedure log3(s: string; ShowTime: boolean);
        var cpt1,cpt2,cpt3 : integer;  
    // ...
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
    cpt1 := 0;
    end;
     
    procedure TForm1.Button2Click(Sender: TObject);
    begin
      cpt2 := 0;
    end;
     
    procedure TForm1.Button3Click(Sender: TObject);
    begin
        cpt3:=0;
    end;  
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      cpt1 := 20;
      cpt2 := 20;
      cpt3 := 20;
    end;
     
    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
        if cpt1 < 20 then  log1(IntToStr(cpt1), True); inc(cpt1);
        if cpt2 < 20 then  log2(IntToStr(cpt2), True);  inc(cpt2);
        if cpt3 < 20 then  log3(IntToStr(cpt3), True);  inc(cpt3);
    end;
    Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

  11. #11
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 719
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Salustre, hombre !

    La procédure tempo, elle est là juste pour simuler une autre vraie procédure consommatrice de temps variable (genre sauvegarde d'un dossier pris dans une liste de dossiers) et pour laquelle je loggue à sa fin l'heure qu'il est.
    L'optimiser ou la remplacer par un timer n'a plus de sens pour cette démo : voir les commentaires rajoutés à mon code (après le tien, ci-dessous).

    Par ailleurs, quelle différence entre ton code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    procedure TForm1.Button2Click(Sender: TObject);
    var
      i : integer;
    begin
      for i := 0 to 20 do begin tempo;
        log2(IntToStr(i), True);
       Application.ProcessMessages;
      end;
    end;
    et un code où Application.ProcessMessages; serait déporté dans la procédure de log ?
    D'ailleurs, si tu regardes bien, tu verras que c'est comme ça qu'est écrit le code sous le bouton 3 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    procedure TForm1.Button3Click(Sender: TObject);
    var
      i : integer;
    begin
      for i := 0 to 20 do begin // simulation liste de dossier
        tempo; // simulation 1 dossier particulier
        log3(IntToStr(i), True);
        //Application.ProcessMessages; déporté à la fin de la procédure de log 
      end;
    end;
    et ça fonctionne.

    Mais, back to beginning, je trouvais que Application.ProcessMessages était une enclume pour écraser une mouche, surtout avec des méthodes aux noms évocateurs comme memo.Repaint, .Refresh (après lui avoir ajouté du texte, ça me semblait cool et adapté), .Update (même remarque), méthodes qui ne fonctionnent pas (ou je ne sais pas m'en servir) sous Linux, mais sous Windows oui.

    That's all, folks !
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  12. #12
    Expert éminent
    Avatar de jurassic pork
    Homme Profil pro
    Bidouilleur
    Inscrit en
    Décembre 2008
    Messages
    3 947
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 3 947
    Points : 9 275
    Points
    9 275
    Par défaut
    il faut exécuter les tâches qui risquent d'être longues dans un thread secondaire. La tâche se déroule en tâche de fond et ne bloque pas l'IHM.
    Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

  13. #13
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 719
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Citation Envoyé par jurassic pork Voir le message
    il faut exécuter les tâches qui risquent d'être longues dans un thread secondaire. La tâche se déroule en tâche de fond et ne bloque pas l'IHM.
    ce qui doit être le cas, vu que j'utilise TProcess pour appeler in fine une commande Linux (celle qui va exécuter la sauvegarde [rsync pour les curieux et les connaisseurs]).

    Mais sinon, je connais le coup des threads, je l'ai testé et utilisé pour la création de gros fichiers (qq gigas) et barre de progression.

    Et pour se faire un peu mal à la tête, y a ça à lire avec Franck Soriano au sax alto et Andnotor à la clarinette (par cette chaleur je ne sais pas si c'est bien raisonnable, )
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  14. #14
    Expert éminent
    Avatar de jurassic pork
    Homme Profil pro
    Bidouilleur
    Inscrit en
    Décembre 2008
    Messages
    3 947
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 3 947
    Points : 9 275
    Points
    9 275
    Par défaut
    ce qui doit être le cas, vu que j'utilise TProcess pour appeler in fine une commande Linux (celle qui va exécuter la sauvegarde [rsync pour les curieux et les connaisseurs]).
    Le TProcess tu l'utilises en mode synchrone ou asynchrone , c'est à dire avec l'option poWaitOnExit ou non ?

    type TProcessOptions = set of (
    poRunSuspended,

    Start the process in suspended state.
    poWaitOnExit,

    Wait for the process to terminate before returning.
    poUsePipes,

    Use pipes to redirect standard input and output.
    poStderrToOutPut,

    Redirect standard error to the standard output stream.
    poNoConsole,

    Do not allow access to the console window for the process (Win32 only)
    poNewConsole,

    Start a new console window for the process (Win32 only)
    poDefaultErrorMode,

    Use default error handling.
    poNewProcessGroup,

    Start the process in a new process group (Win32 only)
    poDebugProcess,

    Allow debugging of the process (Win32 only)
    poDebugOnlyThisProcess

    Do not follow processes started by this process (Win32 only)
    );
    Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

  15. #15
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 719
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Citation Envoyé par jurassic pork Voir le message
    Le TProcess tu l'utilises en mode synchrone ou asynchrone , c'est à dire avec l'option poWaitOnExit ou non ?
    Non, d'où une ch'tite boucle après son lancement :
    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
          with aProcess do
          begin
            Parameters.Clear;
            Executable := 'rsync';
            for i := 0 to slCmd.Count-1 do Parameters.Add(slCmd.Strings[i]);
            Execute; // non bloquant, danger si boucle !, donc while dessous
          end;
     
          While aProcess.Running do
          begin
            if not StoppedByUser then
              logBKP('  ' + src + ', exécution en cours, merci de patienter...', True);
            Sleep(1000);
            //2/8/2016 : "if not" remonté au-dessus + rem app.procmess (déjà dans logBKP)
          end;
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  16. #16
    Expert éminent
    Avatar de jurassic pork
    Homme Profil pro
    Bidouilleur
    Inscrit en
    Décembre 2008
    Messages
    3 947
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Bidouilleur
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2008
    Messages : 3 947
    Points : 9 275
    Points
    9 275
    Par défaut
    et si tu mets un processmessages dans ta boucle d'attente ?
    Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

  17. #17
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 719
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Citation Envoyé par jurassic pork Voir le message
    et si tu mets un processmessages dans ta boucle d'attente ?
    Hé bien, comme indiqué il y était mais je l'ai viré puisque déjà présent dans la proc de log :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
          While aProcess.Running do
          begin
            if not StoppedByUser then
              logBKP('  ' + src + ', exécution en cours, merci de patienter...', True);
            Sleep(1000);
            //2/8/2016 : "if not" remonté au-dessus + rem app.procmess (déjà dans logBKP)
          end;


    Et, rappel, le but de cette discussion était d'envisager le remplacement de ProcessMessage par memo.Repaint ou .Refresh ou autre...
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  18. #18
    Membre chevronné

    Homme Profil pro
    au repos
    Inscrit en
    Février 2014
    Messages
    429
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : au repos

    Informations forums :
    Inscription : Février 2014
    Messages : 429
    Points : 1 884
    Points
    1 884
    Par défaut
    Salut JP,

    Et, rappel, le but de cette discussion était d'envisager le remplacement de ProcessMessage par memo.Repaint ou .Refresh ou autre...
    Pour un composant du genre TMemo, Refresh (Repaint) n'est pas à utiliser pour obtenir un affichage avec défilement.
    Il y a plusieurs messages qui sont en jeu : modification du texte et de la sélection, scrolling barre verticale, affichage.
    De plus, Refresh ne repeint que la zone visible, donc plus de défilement une fois atteint le bas du composant.

    Sous Windows, c'est très simple (en tout cas, depuis la version 7) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    procedure TForm1.Button1Click(Sender: TObject);
    var
      i: integer;
    begin
      for i:= 1 to 50 do
      begin
        Memo1.Append(IntToStr(i));
        Sleep(100);
      end;
    end;
    A noter que la fonction Sleep ne bloque pas le traitement des événements. Donc bon défilement.

    Mais sous Linux, le comportement est différent (je ne parlerais pas de bug): le SelStart ne se positionne pas sur la ligne ajoutée, et Sleep bloque.
    Sans utiliser de thread secondaire, je ne vois que la solution de ProcessMessages.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    procedure TForm1.Button1Click(Sender: TObject);
    var
      i: integer;
    begin
      for i:= 1 to 50 do
      begin
        Memo1.Append(IntToStr(i));
        Memo1.SelStart:= Length(Memo1.Text);
        Application.ProcessMessages;
        Sleep(100);
      end;
    end;
    Cordialement
    Thierry

  19. #19
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 719
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 719
    Points : 15 105
    Points
    15 105
    Par défaut
    Salut, Thierry
    Citation Envoyé par ThWilliam Voir le message
    Mais sous Linux, le comportement est différent (je ne parlerais pas de bug): le SelStart ne se positionne pas sur la ligne ajoutée, et Sleep bloque.
    Sans utiliser de thread secondaire, je ne vois que la solution de ProcessMessages.
    Bon, ben on va en rester là, au final c'est pas bien grave.

    Le seul truc ennuyeux, c'est ce que tu dis en premier
    Citation Envoyé par ThWilliam Voir le message
    Pour un composant du genre TMemo, Refresh (Repaint) n'est pas à utiliser pour obtenir un affichage avec défilement.
    Il y a plusieurs messages qui sont en jeu : modification du texte et de la sélection, scrolling barre verticale, affichage.
    De plus, Refresh ne repeint que la zone visible, donc plus de défilement une fois atteint le bas du composant.
    et qui ne s'invente pas et ne se devine pas non plus...

    Merci à tous.
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 34
    Dernier message: 24/01/2011, 10h02
  2. Existe-t-il un logiciel moins complexe que LaTeX ?
    Par fomazou dans le forum Editeurs / Outils
    Réponses: 4
    Dernier message: 24/12/2006, 13h06
  3. Comment protéger efficacement son application ?
    Par RamDevTeam dans le forum EDI
    Réponses: 3
    Dernier message: 15/11/2005, 09h41
  4. Minimize Maximize perso sur une form autre que Application
    Par sdebrois dans le forum API, COM et SDKs
    Réponses: 5
    Dernier message: 07/03/2005, 17h59
  5. Réponses: 6
    Dernier message: 13/09/2003, 12h42

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