[gelöst] Application.Processmessages (Linux und Windows)

Antworten
angross
Beiträge: 10
Registriert: So 29. Dez 2019, 17:13
OS, Lazarus, FPC: Fedora 36, WinX, Lazarus 2.2.2/2.2.2
CPU-Target: x86_64
Wohnort: Berlin

[gelöst] Application.Processmessages (Linux und Windows)

Beitrag von angross »

Unterscheidet sich Application.ProcessMessages unter Windows von dem unter Linux, so dass Programmabläufe teilweise anders ablaufen? Beispielsweise im Zusammenhang mit der Anzeige eines Dialoges?

Das Programm ist auf einem WinX-Rechner entwickelt und arbeitet dort. Dabei geht es speziell um eine Routine, die alle selektierten Files eines VirtualTreeViews (z.B.von der Festplatte) auf eine Backup-Platte speichern und gegebenenfalls dort dieselben Verzeichnisse erzeugen soll. Vor dem Kopieren zeige ich einen ProgressDialog, der die gerade kopierten files anzeigt und mit dem man den Vorgang gegebenenfalls abbrechen kann.

Code: Alles auswählen

 
  // disable buttons
  changeBedienung(false);
  // show the progress dialog
  FGlobalCancel := false;
  ProgressDialog.SetzFunktion('Kopieren von');
  ProgressDialog.progCallBack := @SetGlobalCancel;
  ProgressDialog.Show;
 
  try
    // get first selected node
    lnksNode := trv_Links.GetFirstSelected(true);
    try
        while (lnksNode <> nil) AND NOT(FGlobalCancel)
        do begin
           // get the pointer to its data
           lnksData := trv_Links.GetNodeData(lnksNode);
           // get complete source path
           wholeLeft := lnksData^.FddAllPath;
           // we need the relative path too
           // attention: relPath does begin with slash!!!
           relLeft := optclass.getRelativePfad(wholeLeft, optclass.aktLinks);
           // get the root path of the destination
           wholeRght := optclass.aktRechts;
           // and same relative path
           wholeRght := wholeRght + relLeft;
 
           ProgressDialog.SetzQuelle(wholeLeft);
           Application.ProcessMessages;
 
           // create the dir if not exist and copy the selected file
           copyFileWithDir(wholeLeft, wholeRght);
 
           // get next selected node
           lnksNode := trv_Links.GetNextSelected(lnksNode);
        end; {while}
 
    except
      on e: Exception do
      begin
        {$IFDEF MSWINDOWS}
        FehlerDialog.SetzFehler(e.Message);
        FehlerDialog.ShowModal;
        {$ELSE}
        MessageDlg(optclass.ProgTitel, e.Message, mtError, [mbOK], 0);
        {$ENDIF}
      end;
    end;
 
Läuft das Programm normal (ohne überwachung), werden zwei Dateien kopiert -- manchmal auch keine -- und dann tut das Teil einfach so, als sei es fertig ...
Lasse ich das Ganze mit BreakPoints laufen, tappert er wirklich alle Files ab und kopiert sie auch.
Schalte ich das Pärchen ProgressDialog.SetzQuelle und Application.ProcessMessages ab, dann funktioniert ebenfalls alles, wie es soll beim normalen Lauf.

Vielleicht ist es irgendein Timing-Problem durch anderes Verhalten von ProcessMessages unter Linux?
Ich muss dazu sagen, dass Linux anscheinend generell einige Probleme mit meinen eigenen Dialogen zu haben scheint, besonders mit modalen. Da kommt gern die Meldung, dass er die nicht anzeigen könne, weil sie schon sichtbar seien -- und dann passieren auch unmögliche Dinge. Deshalb habe ich diese Dialoge durch {IFDEF ...} ausgeklammert und in Linux durch StandardDialogs ersetzt, wie unten gezeigt.

Aber vielleicht hat ja der eine oder andere eine Idee, was da sonst schief laufen könnte. Ich bin jedenfalls erstmal ratlos und für jeden Tipp dankbar.

Gruß
antoine
Zuletzt geändert von angross am Fr 15. Mai 2020, 17:05, insgesamt 2-mal geändert.

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Application.Processmessages (Linux und Windows)

Beitrag von Warf »

Kanns sein das einfach zwischen drin die selektion verloren geht?

Bei processmessages kann die Selektion Geupdated werden, während dem vorgang. Da stellt sich die Frage ob ProcessMessages das ist was du haben möchtest. Wenn du neu zeichnen willst benutz Refresh. Wenn du wirklich ProcessMessages benutzen willst (schaut wegen dem cancel button so aus), lies die liste der Dateien vorher in eine GUI unabbhängige liste ein und iterier dann über die, so kann im GUI egal was geschehen, deine Anwendung wird da durch nicht beeinflusst

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1432
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: Application.Processmessages (Linux und Windows)

Beitrag von fliegermichl »

Zum einen das was Warf schon geschrieben hat und zum anderen fehlen für eine genauere Beurteilung die entscheidenden Routinen. Sofern in "copyFileWithDir" nicht ebenfalls Application.ProcessMessages aufgerufen wird, können Benutzereingaben immer nur nach dem vollständigen Bearbeiten einer Datei verarbeitet werden.

Ich hab jetzt ausserdem nicht nachgeschaut aber liefert TBaseVirtualTree.GetNextSelected nicht nur Nodes im gleichen Index wie die übergebene Node?
Ich iteriere in solchen Fällen rekursiv über den Tree und prüfe den Selected Status der Node selbst.

Das Problem besteht natürlich nicht, wenn dein Tree ohnehin nur einen Nodelevel hat (also keine Unterknoten) hat.

angross
Beiträge: 10
Registriert: So 29. Dez 2019, 17:13
OS, Lazarus, FPC: Fedora 36, WinX, Lazarus 2.2.2/2.2.2
CPU-Target: x86_64
Wohnort: Berlin

Re: Application.Processmessages (Linux und Windows)

Beitrag von angross »

Hallo, Warf, hallo fliegermichl,

danke für eure Antworten -- gibt wieder viel zum Nachdenken für mich :-)

Zuerst einmal scheint es tatsächlich so, dass unter Linux die Selection geupdateted wird -- gesehen bei meinen vorherigen Experimenten mit eigenen Dialogen: dort war es regelrecht zu sehen: wenn der Dialog aufpoppte, verschwanden die Markierungen ... Aber warum?

Unter WinX dagegen ist alles, wie es soll -- daher auch meine Frage nach dem Unterschied in der Behandlung von ProcessMessages ... In dem Zusammenhang ist dein Vorschlag einer unabhängigen Sammlung der selektierten Files eine tolle Idee.

Ich habe in allen Subroutinen keine weiteren ProcessMessages verwendet -- mit ist schon klar, dass das enorme Nachteile hat. Im ganzen source stehen sie nur bei diesen Copy-/Delete-Functions, weil ich gegebenenfalls canceln will. Und dazu reicht es, nach einem kompletten FileCopy abzubrechen (Abfrage auf NOT(FGlobalCancel) in der while-Schleife). Genauso hab ich übrigens z.B. in der eigentlichen Copy-Routine zwar exceptions ausgelöst, sie aber jeweils mit finally alle weiter nach oben geschickt.

Was GetSelectedNode betrifft: Es funktioniert jedenfalls für alle selektierten Nodes, weil ich in einer Subroutine alle Files zusammensammele, die den Kriterien "neuer" und "Waise" (im Gegensatz zur Gegenseite entsprechen:

Code: Alles auswählen

 
      // select only files ...
      if quelData^.FddItemTyp = TDatei
      then begin
        // ... in blue (orphans) or green (newer)
        farbeOkay := (quelData^.FddFarbcode = TBlau)
                      or (quelData^.FddFarbcode = TGruen);
        // ... and add it to the selection
        if farbeOkay
        then trvq.AddToSelection(quelNode);
      end;
 


Das nochmalige Iterieren über die gesamte Liste wollte ich mir damit eigentlich ersparen. Aber mit deinem Einwand

Nodes im gleichen Index


muss ich selbst auch noch mal nachsehen. Da es unter Windows (und Linux ohne den Dialog) funktionierte, habe ich mir bisher weiter keine Gedanken gemacht.

Also erst mal herzlichen Dank
und einen schönen Rest-Sonntag

antoine

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Application.Processmessages (Linux und Windows)

Beitrag von Warf »

angross hat geschrieben:Zuerst einmal scheint es tatsächlich so, dass unter Linux die Selection geupdateted wird -- gesehen bei meinen vorherigen Experimenten mit eigenen Dialogen: dort war es regelrecht zu sehen: wenn der Dialog aufpoppte, verschwanden die Markierungen ... Aber warum?


Warum? Absolut keine Ahnung. Kann grundsätzlich an 2 sachen liegen: Dem Widgetset (also QT oder GTK) oder dem Window Manager/Desktop Environment (KDE, GNOME, XFCE, etc.). Oder natürlich aus ner kombination davon. Wenn dus rausfinden willst kannst du versuchen beides mal umschalten

angross
Beiträge: 10
Registriert: So 29. Dez 2019, 17:13
OS, Lazarus, FPC: Fedora 36, WinX, Lazarus 2.2.2/2.2.2
CPU-Target: x86_64
Wohnort: Berlin

Re: Application.Processmessages (Linux und Windows)

Beitrag von angross »

Ich hab jetzt erst mal die Idee mit den Sammeln der selektierten Nodes (in StringListen) eingebaut und es funktioniert damit. Habe aber noch nicht getestet, wie sich zeitlich dabei viele Selektionen auswirken -- was bei einem Backup-Programm ja öfter mal vorkommt ... Bei den Kurztests gab es keine Verzögerungen.

Da ich in Linux (Fedora) nicht so firm bin, werde ich mich mal mit Widgetsets und Desktop Environment beschäftigen ...

Vielen Dank nochmal.

antoine

Warf
Beiträge: 1908
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Application.Processmessages (Linux und Windows)

Beitrag von Warf »

angross hat geschrieben:Ich hab jetzt erst mal die Idee mit den Sammeln der selektierten Nodes (in StringListen) eingebaut und es funktioniert damit. Habe aber noch nicht getestet, wie sich zeitlich dabei viele Selektionen auswirken -- was bei einem Backup-Programm ja öfter mal vorkommt ... Bei den Kurztests gab es keine Verzögerungen.


Sollte kaum bis keine auswirkungen haben. Stringlisten sind ein Kontinuierlicher Speicherblock, was heißt das caching extrem gut funktioniert, und das drüber laufen extrem schnell ist (wahrscheinlich sogar schneller als dein original loop). Außerdem kopierst du dateien, das kopieren einer datei dauert wahrscheinlich länger als das iterieren über eine liste mit 10.000 einträgen

angross
Beiträge: 10
Registriert: So 29. Dez 2019, 17:13
OS, Lazarus, FPC: Fedora 36, WinX, Lazarus 2.2.2/2.2.2
CPU-Target: x86_64
Wohnort: Berlin

Re: Application.Processmessages (Linux und Windows)

Beitrag von angross »

Hast Recht, das Sammeln in die StringLists hat kaum Auswirkungen, auch nicht bei vielen files. Weil das allerdings vor dem Erscheinen des Dialogs gemacht werden muss, hatte ich eben diese Befürchtung.

das kopieren einer datei dauert wahrscheinlich länger als das iterieren über eine liste mit 10.000 einträgen


Unbestritten und ganz sicher sogar. Auf meinem Großen geht das Kopieren auch nur wirklich schnell, wenn SDXcards und HDs im Spiel sind. Mit USB-Sticks -- auch wenn angeblich USB 3.0 oder höher -- dauert es länger. Auf dem Laptop unter Linux ist sowieso alles ein bisschen langsamer -- wobei im Gegensatz zu WinX Linux auf dem Laptop offenbar mehr an Geschwindigkeit dabei bringt. Hab ich jedenfalls das Gefühl.

angross
Beiträge: 10
Registriert: So 29. Dez 2019, 17:13
OS, Lazarus, FPC: Fedora 36, WinX, Lazarus 2.2.2/2.2.2
CPU-Target: x86_64
Wohnort: Berlin

[gelöst] Application.Processmessages (Linux und Windows)

Beitrag von angross »

Eine Ergänzung -- gerechter Weise:

Einige Wochen nach meinem Beitrag hatte ich auch unter Windows das beschriebene Problem, dass hinter dem ProgressDialog -- also noch während kopiert wurde -- die Selektierung im TVirtualTreeView verschwand, wie ich es für Linux beschrieben hatte. Aus irgendwelchen Gründen hat es dazu etwas mehr Aufwand gebraucht: mehr Files, kopieren auf einen sehr langsamen USBStick, der auch noch thermische Probleme hatte...

Damit betrachte ich diesen Thread als gelöst.

Gruß, antoine
(https://antoinelegra.github.io/)

Antworten