Timer Funktion während FindAllFiles

Für allgemeine Fragen zur Programmierung, welche nicht! direkt mit Lazarus zu tun haben.
fziebell
Beiträge: 6
Registriert: Do 13. Nov 2014, 23:15

Timer Funktion während FindAllFiles

Beitrag von fziebell »

Hallo ans Forum.

Ich benutze Lazarus 1.2.6

Um diverse Laufwerke nach bestimmten Files zu durchsuchen verwende ich die Funktion FindAllFiles.
Das funktioniert auch alles gut.

Werden allerdings größere HDs durchsucht, die dann ein Ergebnis von einigen Tausend Files ergeben dauert
das natürlich durchaus mal eine Minute oder mehr.

Damit der Anwender sieht, dass das Programm noch läuft, wollte ich zum Beispiel ein Shape hin- und herbewegen
oder einen Zähler anzeigen, praktischer und einfacher Weise über einen Timer, der jede Sekunde etwas auslöst.

Leider, sobald ich die Funktion FindAllFiles aufrufe wird der Timer nicht mehr aktualisiert.
Ist die Funktion FindAllFiles beendet, läuft der TImer wieder....

Weis jemand dafür eine Lösung?

Ich weis, dass ich innerhalb einer FindFirst und FindNext Schleife das Problem lösen könnte.
Aber FindAllFiles ist so schön praktisch.......


mfg
fziebell

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: Timer Funktion während FindAllFiles

Beitrag von Michl »

Erstmal herzlich willkommen im Forum!

Du könntest das Ganze in einen Thread packen, der läuft dann nebenher (ist am Anfang aber nicht unbedingt leicht zu verstehen). Siehe http://wiki.freepascal.org/Multithreade ... utorial/de

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

fziebell
Beiträge: 6
Registriert: Do 13. Nov 2014, 23:15

Re: Timer Funktion während FindAllFiles

Beitrag von fziebell »

Vielen Dank für die schnelle Antwort.

Ja, habe ich mir schon gedacht, ist aber ein ganz schöner Aufwand für mein Vorhaben.

Ich entnehme deiner Antwort, das der Timer kein echter (Interrupt)Timer ist und das Ganze so nicht lösbar ist.

Also werde ich wohl leider eine Alternative zu FindAllFiles bemühen müssen. Schade.

mfg
fziebell

Mathias
Beiträge: 6958
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Timer Funktion während FindAllFiles

Beitrag von Mathias »

Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Timer Funktion während FindAllFiles

Beitrag von mschnell »

Rekursive Suche programmieren und "Application.ProcessMessages" in die Scheife einbauen.

Dann bekommst Du Timer-Events.

-Michael

fziebell
Beiträge: 6
Registriert: Do 13. Nov 2014, 23:15

Re: Timer Funktion während FindAllFiles

Beitrag von fziebell »

Ja, wie oben bereits erwähnt....

Habe FindAllFiles jetzt mit aus dem Net für mich angepasste Routine nachgebildet. Timer geht jetzt wie gewünscht.
Interessant: Die "manuelle" Variante ist schneller als FindAllFiles...gut zu Wissen.

Dank ans Forum

Mathias
Beiträge: 6958
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Timer Funktion während FindAllFiles

Beitrag von Mathias »

Habe FindAllFiles jetzt mit aus dem Net für mich angepasste Routine nachgebildet.
Meinst du die Routine von meinem Link ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

ruewa
Beiträge: 153
Registriert: Sa 12. Apr 2014, 14:43

Re: Timer Funktion während FindAllFiles

Beitrag von ruewa »

fziebell hat geschrieben:Interessant: Die "manuelle" Variante ist schneller als FindAllFiles...
Gemessen oder gefühlt? Kannst Du näheres dazu sagen, denn je nach Umfang kann eine Subdirectories einschließende Suche ja schon sehr zeitraubend werden.

Gruß Rüdiger

fziebell
Beiträge: 6
Registriert: Do 13. Nov 2014, 23:15

Re: Timer Funktion während FindAllFiles

Beitrag von fziebell »

@ Mathias:

Diesen Link hatte ich auch gefunden, aber es gibt andere die ähnlich funktionieren, da habe ich mich bedient.

@ruewa:


Sogar gemessen.

Bei der Anpassung der Routine an meine Zwecke habe ich ich sowohl mir der manuellen Routine, als auch mit findAllFiles experimentiert.

1. PC mit HD *.* ca. 240.000 Dateien

FindAllFiles ca. 45 Sekunden
Manuell ca. 35 Sekunden

2. PC mit SSD *.exe ca. 4050 Dateien

FindALLFiles ca. 15 Sekunden
Manuell ca. 10 Sekunden

Und bei manuell springt er auch noch alle 500ms den Timer an...

Ich bin überzeugt das sich die manuelle Routine noch optimieren lässt.
Da werde ich dran gehen, wenn ich dafür ein paar Stunden Zeit habe.

Gruß

fziebell
Beiträge: 6
Registriert: Do 13. Nov 2014, 23:15

Re: Timer Funktion während FindAllFiles

Beitrag von fziebell »

Zu erwähnen wäre noch das ich vor Jahren eigentlich das Problem mit Delphi 5 und Delphi 2007 gelöst hatte(allerdings mit irgendeiner spezial LIB von Torrys).
Damals haben solche Suchen nie länger als 5-10 Sekunden gedauert, trotz Timer interrupt.

Kann natürlich sein, das damals auch wesentlich weniger Files und SubDirs vorhanden waren,

Gruß

fziebell
Beiträge: 6
Registriert: Do 13. Nov 2014, 23:15

Re: Timer Funktion während FindAllFiles

Beitrag von fziebell »

Sehr interessant....

Das dauert immer noch ärgerlich lange.

Da ich ja innerhalb der FindFirst und FindNext Schleife mit application.processmessages die Ausführung des Timers erzwinge, habe ich mal den Timer von 500ms auf 1000ms gesetzt.
Das bringt ein ca. 20% schnelleres Ergebnis. Längere Zeiten von 1500 oder 2000ms bringen keine höhere Geschwindigkeit.

Intuitiv dachte ich , dass application.processmessages eine weitere Bremse wäre, da damit ja alle aufgelaufenen Windows Messages abgearbeitet werden.

Ich ersetzte den Timer durch eine manuelle GetTickCount Routine, die immer abfragt, ob eine Sekunde um ist und dann z.B. einen Zähler auf dem Screen hochzählt.
Aber das brachte reproduzierbar 0% mehr Speed.

Also kann ich beruhigt application.processmessages und den Timer verwenden.


Aus dieser Quelle und den Folgeseiten habe ich mich bedient. Sehr schöne Ansätze zum Thema...

http://www.delphipraxis.net/2235-verzei ... uchen.html


Gruß

ruewa
Beiträge: 153
Registriert: Sa 12. Apr 2014, 14:43

Re: Timer Funktion während FindAllFiles

Beitrag von ruewa »

Was ich jetzt nicht ganz verstehe, ist
fziebell hat geschrieben:Da ich ja innerhalb der FindFirst und FindNext Schleife mit application.processmessages die Ausführung des Timers erzwinge, habe ich mal den Timer von 500ms auf 1000ms gesetzt.
Das bringt ein ca. 20% schnelleres Ergebnis. Längere Zeiten von 1500 oder 2000ms bringen keine höhere Geschwindigkeit.
"Mit application.processmessages die Ausführung des Timers erzwingen", was meinst Du denn damit? Der Timer (jedenfalls der LCL-TTimer) läuft in einem eigenen Thread und triggert von dort aus irgendwann das Timer-Event. Mit ProcessMessages würde dann die Abarbeitung des OnTimer-Events, falls eines vorliegt, angeregt? Und dazu triggerst Du bei jedem FindNext aufs neue ein ProcessMessages - so interpretiere ich Deinen Satz. Aber dann verstehe ich überhaupt nicht, was eine Verlängerung des Timerintervalls an der Performance ändern würde? Wie führst Du denn die Zeitmessung durch? (Ggfls. schau mal hier rein: http://www.lazarusforum.de/viewtopic.php?f=29&t=8081)

Wozu verwendest Du überhaupt einen Timer? Es würde doch vollauf genügen, in der FindNext-Schleife einen Zähler zu inkrementieren. Du weißt, Du hast 260.000 Dateien, die in 45 Sekunden durchgenudelt werden, also nicht ganz 6000 Dateien pro Sekunde. Es geht, wenn ich dich richtig verstehe, ja nur um eine periodische Bildschirmaktualisierung. Du könntest es doch auch so machen: Wenn der Zähler die 3000 (oder was auch immer) erreicht, aktualisierst Du die Anzeige und triggerst ein ProcessMessages, und stellst den Zähler wieder auf Null zurück. Wenn Du andererseits 6000 mal pro Sekunde ProcessMessages aufrufst, dann kostet das schon richtig Zeit.

Gruß Rüdiger
Zuletzt geändert von ruewa am Mo 24. Nov 2014, 00:04, insgesamt 2-mal geändert.

soerensen3
Beiträge: 104
Registriert: Fr 22. Jun 2012, 01:51
OS, Lazarus, FPC: Fedora-Linux 23 (Korora) Lazarus 1.6 FPC 3.0
CPU-Target: 64Bit
Wohnort: Bonn

Re: Timer Funktion während FindAllFiles

Beitrag von soerensen3 »

Das eleganteste wäre vielleicht auch ein Thread: http://wiki.freepascal.org/Multithreade ... utorial/de
Das ist aber nicht ganz trivial da du außerhalb des Threads nicht auf Threadvariablen zugreifen solltest (Zumindest nicht ohne Vorkehrungen).
Dafür könntest du mit synchronize (Siehe Link) den Status übergeben. Vielleicht solltest du die dann trotzdem nicht nach jeder Datei aufrufen. Dann brauchst du auch nicht mehr ProcessMessages aufzurufen da das ganze parallel zu deinem Programm läuft.
Vielleicht ist das aber auch zu komplex für den Anfang aber in dem Falle sollte es nicht allzu schwer zu implementieren sein.
Kannst dir ja mal die Beispiele angucken und entscheiden ob du das versuchen willst.
Der Vorteil ist, dass es dann auch auf mehrere Prozessoren verteilt wird (Haupthread und Nebenthread).
Die Geschwindigkeit ist natürlich auch abhängig von der verwendeten Festplatte und deinem Prozessor, weshalb man die Geschwindigkeiten nicht unbedingt vergleichen kann.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Timer Funktion während FindAllFiles

Beitrag von mschnell »

soerensen3 hat geschrieben:Dafür könntest du mit synchronize (Siehe Link) den Status übergeben.
Wie schon oft beschrieben, ist Synchonze hier kontra-produktiv, da der Thread dann auf den Mainthread warten muss. Reie Status-Meldungen an den Mainthread macht man mit ApplicationQueueAsync Call oder (bei Delphi und neuerer fpc-RTL) mit TThread.Queue.

-Michael

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Timer Funktion während FindAllFiles

Beitrag von mse »

ruewa hat geschrieben:Der Timer (jedenfalls der LCL-TTimer) läuft in einem eigenen Thread und triggert von dort aus irgendwann das Timer-Event.
Da wäre ich mir nicht so sicher da es vom widgetset abhängt.

Antworten