Salut,

aujourd'hui je constate un phénomène étrange, dans une boucle de mon logiciel de sauvegarde, constitué d'une IHM en Lazarus 1.4/FPC 2.6.2 pilotant un TProcess qui fait appel à "rsync" sous Linux.
Pour les gens qui regardent par la fenêtre, je dirais que c'est l'équivalent de Robocopy ou Xcopy, bref, un machin qui prend des dossiers d'un côté et qui les recopie de l'autre, pour faire court et simple.

J'ai une liste de dossiers dans un TMemo qui est parcourue par une boucle toute bête genre
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
for i := 0 to memoChemins.Lines.Count-1 do begin // liste des chemins à sauver
  if StoppedByUser then Break;
  ControlAndJob(memoChemins.Lines[i]) // appel rsync
end;
et j'ai implémenté un bouton "Stop" pour... arrêter, en cas de souci ou autre.
Cette affaire fonctionne bien sauf pour les gros dossiers puisqu'il faut attendre le passage au dossier suivant pour sortir de la boucle si le bouton a été cliqué en cours de boucle.
Et ça c'est pas top.

J'ai donc rajouté un test dans le bouton :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
procedure TMainForm.btnStopClick(Sender: TObject);
begin
  StoppedByUser := True;
  if aProcess.Running then
  begin
    FpKill(aProcess.processID, SIGINT); // pour terminer la tâche "rsync"
    log('  +++ Processus interrompu par l''utilisateur +++', True);
  end;   
end;
J'ai la preuve que le clic est pris en compte puisque la boucle principale va s'arrêter (donc le boolean est bien passé à "True") mais je ne vois pas le message être loggé dans le TMemo de log malgré un Application.PM dans la proc de log, appelée toutes les secondes par une autre boucle, quelque part dans ControlAndJob de la boucle principale :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
  Sleep(1000); // juste au dessus il y a le lancement du aProcess avec les params qui vont bien
  While aProcess.Running do begin
    if not StoppedByUser then
      log(src + ', exécution en cours, merci de patienter...', True);
    Sleep(1000);
  end;
et je vois bien, toutes les secondes, le temps loggé (option "True" de ma proc de log) et le message d'exécution : donc ici le aProcess est bien "running" mais dans le btnStopClick il ne l'était pas ?
Mais comment c'est possible un truc pareil ?

---
Dit autrement :
Je lance le job, ça lance un TProcess avec les bons paramètres, on entre dans la boucle (je vois passer les messages), je clique sur le bouton --> le boolean est pris en compte (je le verrai plus tard) mais pas le test sur l'état du TProcess, et là ça dépasse mes compétences...

Et le plus fou, c'est que je m'en suis royalement sorti autrement, et ça fonctionne tip-top avec cette nouvelle manière ! Le bouton, plus simple tu meurs :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
procedure TMainForm.btnStopClick(Sender: TObject);
begin
  StoppedByUser := True; // demande d'arrêt pendant tâche longue (gros dossier)
end;
la boucle, à peine rallongée par l'autre branche du test :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
  Sleep(1000); 
  While aProcess.Running do begin
    // 14/08 : mise en place de .Terminate : --test OK !--
    if StoppedByUser then begin 
      aProcess.Terminate(iExitStatus); // valeur ignorée (cf. aide)
      log('  +++ Processus interrompu par l''utilisateur +++', True);
    end
    else
      log(src + ', exécution en cours, merci de patienter...', True);
    Sleep(1000);
  end;
D'habitude, quand j'écris (comme un roman) le problème que je rencontre, en général je trouve une solution mais là, pas d'idée...
Et vous ?