Die LCL-Time werden vom Widgetset oder Betriebssystem bereitgestellt und dann in die Message-Queue der Anwendung eingereiht. Threads werden nicht verwendet.mse hat geschrieben: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.
Timer Funktion während FindAllFiles
-
- Lazarusforum e. V.
- Beiträge: 3178
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: Timer Funktion während FindAllFiles
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
-
- 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
Das ist ein Irrtum. Der Timer der LCL verwendet Widget-Set Funktionialitäten (z.B. Windows, oder GTK) um das Event direkt im Mainthread zu schmeißen.ruewa hat geschrieben: Der Timer (jedenfalls der LCL-TTimer) läuft in einem eigenen Thread und triggert von dort aus irgendwann das Timer-Event.
Edit: Socke war schneller

-Michael
Re: Timer Funktion während FindAllFiles
Stimmt, Ihr habt recht. Ich habe das für GTK gerade nochmal nachgeschlagen: https://developer.gnome.org/glib/unstab ... source-new. Danke für die Korrektur.
Es ist der TFPTimer, der eigene Threads verwendet:
Okay, das ändert aber nichts daran, daß fziebell gut beraten wäre, den Timer rauszuschmeißen und den 260.000-fachen Aufruf von Application.ProcessMessages zu reduzieren. Eine simple Zählvariable innerhalb der Schleife kostet am wenigsten Ressourcen und ob der Bildschirm alle 0,2 Sekunden oder alle 0,6 Sekunden aktualisiert wird, spielt in dem Fall keine Rolle - es geht ja nur darum, daß das Programm keine dreiviertel Minute lang einfriert.
Gruß Rüdiger
Es ist der TFPTimer, der eigene Threads verwendet:
Ach, das Gedächtnis...Unit fptimer, Zeile 169:
Default implementation. Threaded timer, one thread per timer.
Okay, das ändert aber nichts daran, daß fziebell gut beraten wäre, den Timer rauszuschmeißen und den 260.000-fachen Aufruf von Application.ProcessMessages zu reduzieren. Eine simple Zählvariable innerhalb der Schleife kostet am wenigsten Ressourcen und ob der Bildschirm alle 0,2 Sekunden oder alle 0,6 Sekunden aktualisiert wird, spielt in dem Fall keine Rolle - es geht ja nur darum, daß das Programm keine dreiviertel Minute lang einfriert.
Gruß Rüdiger
-
- 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
Dabei sollte man aber berücksichtigen, dass man auch nicht die Suche abbrechen kann oder das Programm auf normalen Weg beenden kann (zumindest nicht flüssig). Aber das ist vielleicht auch in deinem Fall akzeptabel (Kommt auf den Einzelfall an).
ApplicationQueueAsyncCall oder Queue sind wahrscheinlich die bessere Variante, aber auch schwerer zu verwenden, da kein Beispiel dazu da ist (oder war da nicht eins im examples ordner?). Die Seite zu Multithreads müsste da wahrscheinlich auch mal angepasst werden.
Ich würde wahrscheinlich versuchen es mit Threads umzusetzen, aber will dir da auch nichts aufzwingen. Zumal man sich mit Threads auch eine Menge Ärger einhandeln kann, da sie gerade beim debugging sehr problematisch sind.
ApplicationQueueAsyncCall oder Queue sind wahrscheinlich die bessere Variante, aber auch schwerer zu verwenden, da kein Beispiel dazu da ist (oder war da nicht eins im examples ordner?). Die Seite zu Multithreads müsste da wahrscheinlich auch mal angepasst werden.
Ich würde wahrscheinlich versuchen es mit Threads umzusetzen, aber will dir da auch nichts aufzwingen. Zumal man sich mit Threads auch eine Menge Ärger einhandeln kann, da sie gerade beim debugging sehr problematisch sind.
-
- 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
-> TThread.Terminatesoerensen3 hat geschrieben:Dabei sollte man aber berücksichtigen, dass man auch nicht die Suche abbrechen kann
Funktioniert ansonsten genau wie Synchronize, nur dass bei QueueAsynCall noch eine Zahl mit übergeben werden kannsoerensen3 hat geschrieben:ApplicationQueueAsyncCall oder Queue sind wahrscheinlich die bessere Variante, aber auch schwerer zu verwenden.
-Michael
-
- 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
Ich meinte bei dem TImer, wenn Application.ProcessMessages nur einmal pro Sekunde aufgerufen wird.mschnell hat geschrieben: soerensen3 hat geschrieben:Dabei sollte man aber berücksichtigen, dass man auch nicht die Suche abbrechen kann
-> TThread.Terminate
Das ist eben der Vorteil bei Threads. Allerdings funktioniert TThread.Terminate nur, wenn im Execute Teil regelmäßig geprüft wird ob TThread.Terminated True ist.
Re: Timer Funktion während FindAllFiles
Das habe ich gerade mal probiert, an einem alten Projekt, das mithilfe von ImageMagick alle jpgs im Verzeichnis analysiert und ab einer bestimmten Grenzgröße verkleinert. Die Form enthält u.a. einen Run-Button und einen Close-Button. Die Bearbeitungsschleife ist innerhalb der OnClick-Prozedur des Run-Buttons.soerensen3 hat geschrieben:Dabei sollte man aber berücksichtigen, dass man auch nicht die Suche abbrechen kann oder das Programm auf normalen Weg beenden kann (zumindest nicht flüssig).
Dazu habe ich der Form eine Boolsche Variable namens "Running" spendiert, diese bei OnCreate auf false initialisiert und folgenden Code in die RunBtnClick-Prozedur eingefügt:
Code: Alles auswählen
procedure TForm1.RunBtnClick(Sender: TObject);
var
cnt : integer;
{...}
begin
Running := not Running;
if Running then RunBtn.Caption := '&Stop'
else begin
RunBtn.Caption := '&Ok';
exit;
end;
Application.ProcessMessages;
{...}
Cnt := -1;
try
for i := 0 to FileList.Count - 1 do
begin
if not Running then break;
inc(cnt);
if cnt = 100 then
begin
Application.ProcessMessages;
cnt := 0;
end;
{...}
finally
{...}
Running := false;
RunBtn.Caption := '&Ok';
end;
Das funktioniert völlig problemlos, die Ausführung stoppt nach einem Stop-Click zuverlässig, sobald infolge der cnt=100-Bedingung ein ProcessMessages aufgerufen wird. Was interessanterweise während der Abarbeitung der Schleife nicht funktioniert, ist der Close-BitBtn (der einfach via Kind auf bkClose gestellt ist). Ich vermute, der fragt noch irgendein CanClose-Flag ab, das habe ich jetzt nicht weiter untersucht.
Gruß Rüdiger
Edit: Aufräumaktion im Finally-Block hinzugefügt, so kann's verwendet werden ("Running: Boolean;" muß dann noch in die Formdeklaration eingesetzt werden).
Zuletzt geändert von ruewa am Di 25. Nov 2014, 13:00, insgesamt 3-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
Ok aber Cnt ist ja nicht 3000 in dem Fall sondern 100, dann reagiert er schneller. Da kann man ja versuchen einen sinnvollen Wert zu finden.
Das mit dem Close liegt vermutlich daran, dass Running ja nicht auf False gesetzt wird. Durch ein OnClose Ereignis könnte man das vermutlich lösen.
Das mit dem Close liegt vermutlich daran, dass Running ja nicht auf False gesetzt wird. Durch ein OnClose Ereignis könnte man das vermutlich lösen.
Re: Timer Funktion während FindAllFiles
Nein, in meinem Fall viel langsamer, weil dabei 100 Dateien eingelesen werden. Ist aber auch egal, die 3000 bezogen sich auf die Zahlen von fziebell, bei ihm würde das eine halbe Sekunde dauern. Die Zahl ist völlig beliebig.soerensen3 hat geschrieben:Ok aber Cnt ist ja nicht 3000 in dem Fall sondern 100, dann reagiert er schneller.
Das "Running" hat mit dem Close-Event nichts zu tun, das ist meine eigene Variable, die wird nur in runBtnClick ausgewertet. Ehrlich gesagt, ich hab mir nicht mal die Mühe gemacht, das am Ende der Prozedur aufzuräumen, mich hat nur interessiert, ob es prinzipiell funktioniert. Das flieg jetzt auch wieder raus...
Gruß Rüdiger
-
- 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
Nicht ganz, entscheidend ist folgende Zeile:ruewa hat geschrieben:Das "Running" hat mit dem Close-Event nichts zu tun, ...
Code: Alles auswählen
if not Running then break;
Re: Timer Funktion während FindAllFiles
Langsam! Die Ausführung wird gestartet, und danach spielt sich alles innerhalb der RunBtnClick-Methode ab. Dort wird Running auf true gesetzt und der Button auf "Stop" umbenannt. Danach geht's in die For..do-Schleife, wo die eigentliche Bearbeitung stattfindet. Klicke ich jetzt ein zweites Mal auf den (jetzt Stop-) Button, wird die RunBtn-Click-Methode ein zweites Mal aufgerufen. Das passiert aber erst, nachdem innerhalb der Schleife cnt=100 erreicht und das ProcessMessages aufgerufen wird. Dann wird der zweite Durchlauf der RunBtnClick-Methode dazwischengeschoben, stellt dort aber im Wesentlichen nur Running wieder auf false und bricht dann via exit ab. Dann geht es zurück in die Schleife, die beim nächsten Durchlauf abgebrochen wird, weil inzwischen das Running-Flag wieder auf false steht.soerensen3 hat geschrieben:Nicht ganz, entscheidend ist folgende Zeile:ruewa hat geschrieben:Das "Running" hat mit dem Close-Event nichts zu tun, ...Sonst verzögert die Ausführung das Beenden vom Programm.Code: Alles auswählen
if not Running then break;
Was soll ich sagen? So funktioniert es, das war mir nicht von vorneherein klar. Der Zweitaufruf von RunBtnClick wird genauso in die Queue gestellt wie die Aktivierung des Close-Buttons. Schiebt man nun ein ProcessMessages dazwischen, wird der Zweitaufruf von RunBtnClick zwischendurch ausgeführt, der Close-Befehl aber nicht (der wird erst ausgeführt, wenn die Schleife regulär beendet ist). Der Close-Mechanismus weiß überhaupt nichts von der Existenz der "Running"-Variable. Warum, weshalb - keine Ahnung...
Aber vielleicht reden wir auch aneinander vorbei. Klar ist: Mein obiger Code führt nicht zu einem instantanen Abbruch, die Schleife läuft solange weiter, bis das Programm via ProcessMessages aktualisiert wird. Das Intervall dafür kann man aber frei wählen, und halt auch ohne Timer, Threads und dergleichen.
Gruß Rüdiger
-
- 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
Eine Sekunde Delay ist doch wohl flott genug zum Abbrechen, oder ?soerensen3 hat geschrieben:Ich meinte bei dem TImer, wenn Application.ProcessMessages nur einmal pro Sekunde aufgerufen wird.
Das muss man immer !soerensen3 hat geschrieben:Das ist eben der Vorteil bei Threads. Allerdings funktioniert TThread.Terminate nur, wenn im Execute Teil regelmäßig geprüft wird ob TThread.Terminated True ist.
Code: Alles auswählen
...
procedure ...Execute;
...
while not Terminated do begin
...
end;
...