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
et j'ai implémenté un bouton "Stop" pour... arrêter, en cas de souci ou autre.
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;
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 :
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
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;
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 ?
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;
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 :
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 procedure TMainForm.btnStopClick(Sender: TObject); begin StoppedByUser := True; // demande d'arrêt pendant tâche longue (gros dossier) 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...
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;
Et vous ?
Partager