Timer Funktion während FindAllFiles
Timer Funktion während FindAllFiles
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
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
Re: Timer Funktion während FindAllFiles
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
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;
Re: Timer Funktion während FindAllFiles
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
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
-
- 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
Vielleicht hilft dir dies weiter: http://www.delphi-treff.de/tipps-tricks ... en-suchen/
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
-
- 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
Rekursive Suche programmieren und "Application.ProcessMessages" in die Scheife einbauen.
Dann bekommst Du Timer-Events.
-Michael
Dann bekommst Du Timer-Events.
-Michael
Re: Timer Funktion während FindAllFiles
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
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
-
- 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
Meinst du die Routine von meinem Link ?Habe FindAllFiles jetzt mit aus dem Net für mich angepasste Routine nachgebildet.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
Re: Timer Funktion während 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.fziebell hat geschrieben:Interessant: Die "manuelle" Variante ist schneller als FindAllFiles...
Gruß Rüdiger
Re: Timer Funktion während FindAllFiles
@ 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ß
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ß
Re: Timer Funktion während FindAllFiles
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ß
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ß
Re: Timer Funktion während FindAllFiles
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ß
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ß
Re: Timer Funktion während FindAllFiles
Was ich jetzt nicht ganz verstehe, ist
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
"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)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.
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.
-
- 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
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.
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.
-
- 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
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.soerensen3 hat geschrieben:Dafür könntest du mit synchronize (Siehe Link) den Status übergeben.
-Michael
-
- 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
Da wäre ich mir nicht so sicher da es vom widgetset abhängt.ruewa hat geschrieben:Der Timer (jedenfalls der LCL-TTimer) läuft in einem eigenen Thread und triggert von dort aus irgendwann das Timer-Event.