Enchaînement des messages système, Application.ProcessMessages, etc.
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:
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:
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:
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 ? :koi:
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:
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:
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 ?