[gelöst] Sleep - Ungewohntes Verhalten?

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Erwin
Beiträge: 286
Registriert: Mi 16. Sep 2009, 14:15
OS, Lazarus, FPC: Xubuntu 22.04 / x86_64_linux-gtk 2 / L 2.2.0 / FPC 3.2.2

[gelöst] Sleep - Ungewohntes Verhalten?

Beitrag von Erwin »

Hallo Zusammen.

Der Sleep-Befehl verhält sich meiner Meinung nach komisch, und ganz anders als ich mich von früher (von Delphi) her erinnern kann. Ich habe folgenden Code geschrieben:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var i:Integer;
begin
  for i:=10 downto 1 do
  begin
    Button1.Caption:=IntToStr(i);
    sleep(1000);
  end;
end;
 

Erwartet hatte ich, dass er dann in Sekundentakt herunter zählt. Da sleep die Ausführung des Programms um die Eingetragene Zeit (in Tausendstel Sekunden) eben an der Stelle anhalten soll. So steht es zumindest auch im FreePascal-Buch.
Aber bei mir tut sleep gar nicht an der Stelle anhalten, sondern scheinbar zählt er alle sleep zusammen, also alle 10 Durchläufe, wartet die Ganze Zeit ab, und führt dann all den gesamten restlichen Programmteil aus. Zuerst passiert also gar nicht, außer dass der Button gedrückt aussieht, für 10 Sekunden, und dann erscheint die 1. Keine Sekunden-Herunter-Zählen.
Und das passiert in den Unterschiedlichsten Variationen. Sogar wenn ich Button2Click(Sender) einfüge, wo dann sleep ausgeführt wird (somit also sleep auslagere, in der Hoffnung dass er dann zuerst nur den Code im Button2 abarbeitet), wird all dies zusammen gezählt, und nach Ablauf der gesamten Zeit, dann der Restliche Code ausgeführt.
Soll das so sein? Und wie hat man das überhaupt geschafft? Weil meiner Meinung nach muss das doch recht aufwendig sein, erst mal alle aus zu führenden sleep zusammen zu zählen, und dann hernach nach der gesamten Wartezeit die restlichen Code-Zeilen dann ohne sleep auszuführen?

Danke.
Zuletzt geändert von Erwin am Do 17. Mai 2018, 17:43, insgesamt 1-mal geändert.
Lazarus 2.2.0 / FP 3.2.4

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Sleep - Ungewohntes Verhalten?

Beitrag von m.fuchs »

Für folgendes vor deiner Sleep-Anweisung ein:

Code: Alles auswählen

Application.ProcessMessages;


Hintergrund: Während dein Prozedur abgearbeitet wird, kann das Programm keine Messages verarbeiten. Ohne diese Verarbeitung wird die Ausgabe aber auch nicht aktualisiert.

Schön ist das Konstrukt aber so oder so nicht. Probier doch mal einen Timer aus.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Sleep - Ungewohntes Verhalten?

Beitrag von wp_xyz »

Abgesehen davon, dass dein Programm bei mir wunderbar funktioniert: Lass die Finger von Sleep - da versuchen die Technologen die Rechner immer schneller zu machen, und du verschenkst die Rechnen-Power mit Sleep! Versuche mal, während des Sleep-Zyklus das Formular zu verschieben, und überleg dir schon mal Ausreden für die Beschimpfungen deiner Kunden.

Nimm stattdessen einen Timer. ButtonClick startet den Timer (Timer.Enabled := true), und im OnTimer-Event des Timers zählst du die Zähl-Variable herunter und gibst ihren Wert in der Button-Caption aus. Und versuche jetzt ebenfalls, das Formular während des laufenden Timers zu verschieben:

Code: Alles auswählen

var
  zaehler: Integer;
 
procedure TForm1.Button2Click(Sender: TObject);
begin
  zaehler := 10;
  Button2.Caption := IntToStr(zaehler);
  Timer1.enabled := true;
end;
 
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  dec(zaehler);
  Button2.Caption := IntToStr(zaehler);
  if zaehler = 1 then Timer1.Enabled := false;
end;

Erwin
Beiträge: 286
Registriert: Mi 16. Sep 2009, 14:15
OS, Lazarus, FPC: Xubuntu 22.04 / x86_64_linux-gtk 2 / L 2.2.0 / FPC 3.2.2

Re: Sleep - Ungewohntes Verhalten?

Beitrag von Erwin »

Danke.

@ m.fuchs,
den Befehl habe ich bei der Suche sogar 2 mal gefunden, glaube ich. Habe es aber nicht so ganz verstanden, vermutlich weil ich mich auch etwas unwohl fühlte, den Befehl einzufügen. Ich kenne es von Früher anders, ohne den Befehl.
Sleep und PrecessMessages kommen sich also in die Quere, einfach ausgedrückt? So ist das also vermutlich? Danke.
Habe gleich gründlich getestet: Direkt vor sleep 'muss' es nicht sein, aber außerhalb for geht es auch nicht. Also dann doch gleich besser direkt vor sleep. Außerdem wird da scheinbar nichts dauerhaft freigeschaltet, sondern nur für den einen kommenden sleep.
Bis jetzt habe ich es auch dann mit dem Timer gemacht, ist aber halt eine Extra Komponente. Und dann wird das Banale zerlegt ... . Und Timer ... habe komischerweise ungutes Gefühl damit. Aber wenn man sleep mit der einen Funktion machen muss, das passt mir auch nicht. Also kann jetzt eh so bleiben, wie es war/ist.

@ wp_xyz
So habe ich das Problem bisher auch gelöst. Danke. Habe nämlich eh schon überlegt, ob ich nachfragen soll, wie genau ihr das sleep-Dilema mit dem Timer löst? Ob es also Programmier-Still-Mäßig in Ordnung ist, den Timer sich selbst abschalten zu lassen.

Also ich habe bei der Nutzung von sleep das Formular bewegt, aber da passierte nichts aufregendes. Dafür habe ich nebenbei festgestellt, dass auch bei sleep man andere Buttons drücken kann. Zwar wird es erst nach dem sleep dies dann ausgeführt, aber eigentlich hatte ich gehofft, dass da dann gar nichts geht. Was mit ein Grund war, weshalb ich Timer meiden wollte. Womit für mich ein wichtiger Grund gegen Timer weg fällt.
Lazarus 2.2.0 / FP 3.2.4

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

Re: [gelöst] Sleep - Ungewohntes Verhalten?

Beitrag von Mathias »

Versuche mal, während des Sleep-Zyklus das Formular zu verschieben, und überleg dir schon mal Ausreden für die Beschimpfungen deiner Kunden.

Ein altbekanntes Problem von Windoof, unter Linux kann man das Fenster ohne Probleme rum schieben, sogar ver-grössern/kleinern geht.

Aber Sleep würde ich trotzdem meiden, ausser es geht nicht anderes, zB. ein Com-Port initialisieren.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Sleep - Ungewohntes Verhalten?

Beitrag von m.fuchs »

Erwin hat geschrieben:den Befehl habe ich bei der Suche sogar 2 mal gefunden, glaube ich. Habe es aber nicht so ganz verstanden, vermutlich weil ich mich auch etwas unwohl fühlte, den Befehl einzufügen. Ich kenne es von Früher anders, ohne den Befehl.
Sleep und ProcessMessages kommen sich also in die Quere, einfach ausgedrückt? So ist das also vermutlich? Danke.

Nein, die kommen sich nicht in die Quere. Die Tatsache dass eine Programmabarbeitung läuft (und dazu gehört auch dein Sleep) sorgt dafür dass die angefallen Messages nicht abgearbeitet werden. Ohne diese Abarbeitung gibt es aber kein Update der Programmoberfläche. Mit dem Aufruf von ProcessMessages erzwingst du die Message-Verarbeitung, die sonst läuft wenn dein Programm nichts zu tun hast.

Erwin hat geschrieben:Habe gleich gründlich getestet: Direkt vor sleep 'muss' es nicht sein, aber außerhalb for geht es auch nicht. Also dann doch gleich besser direkt vor sleep. Außerdem wird da scheinbar nichts dauerhaft freigeschaltet, sondern nur für den einen kommenden sleep.

Da wird überhaupt nichts freigeschaltet sondern eben die Messages verarbeitet. Deswegen muss jedes Mal wenn sich etwas ändert (und weiterhin Programmcode abgearbeitet wird) diese Message-Verarbeitung getriggert werden.

Erwin hat geschrieben:Ob es also Programmier-Still-Mäßig in Ordnung ist, den Timer sich selbst abschalten zu lassen.

Klar, das ist ein übliches Vorgehen.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

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: [gelöst] Sleep - Ungewohntes Verhalten?

Beitrag von mschnell »

Definition für Sleep():

Mein Programm (genauer: Thread) tut mindestens die angegebene Zeit (möglicherweise aber auch viel länger) nichts (reagiert also auch auf nichts) und die CPU wird so lange den anderen Aktivitäten auf dem Rechner überlasen. Im Main-5trehred eines Lazarus-Programms also höchst sinnlos.

Endlos- (oder auch generell länger laufende, wie hier 10 Sekunden) Schleife im Main Thread eines Lazarus-Programms: verboten !

In Worker-Threads (TThread) können Enlos-Schleifen und sleep()durchaus sinnvoll sein.

-Michael

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

Re: [gelöst] Sleep - Ungewohntes Verhalten?

Beitrag von fliegermichl »

mschnell hat geschrieben:Definition für Sleep():


In Worker-Threads (TThread) können Enlos-Schleifen und sleep()durchaus sinnvoll sein.



Ja manchmal sogar unumgänglich. Wenn man z.B. an einem Port pollt und auf irgendwas in einer Schleife wartet, geht ohne Sleep die CPU Belastung auf 100%.

Erwin
Beiträge: 286
Registriert: Mi 16. Sep 2009, 14:15
OS, Lazarus, FPC: Xubuntu 22.04 / x86_64_linux-gtk 2 / L 2.2.0 / FPC 3.2.2

Re: [gelöst] Sleep - Ungewohntes Verhalten?

Beitrag von Erwin »

@ Mathias
Stimmt ja, die meisten nutzen Windows. Aber unter einer Linux-Distrie kann ich problemloser werkeln. Außerdem kann man auch die Buttons so schön bunt gestalten, was unter Windows nicht geht.
Danke für die Vorwarnung. Unter Win will ich lieber gar nichts riskieren, weil eine Neuinstallation inzwischen (wegen vielen Updates) 0,5-1 Tag dauern dürfte.

@ m.fuchs
Das brauchte mich auf die Idee, den Befehl also auch nach sleep einsetzen, je nach dem ob zuerst (vor der Datenausgabe) die Zeit abgewartet werden soll, oder umgekehrt. Funktioniert auch wunderbar.
Also das Ganze kenne ich von Früher anders. Dass ist mir jedenfalls neu, dass erst alles abgearbeitet wird, bevor dann das Ergebnis (Daten und Grafik) sozusagen Ausgegeben (Dargestellt) wird. Aber deshalb kam es mir also so vor, als würde er die sleep-Zeiten zusammen zählen.
Hm... weiß nicht so recht, ob das besser oder schlechter ist. Jedenfalls fallen dadurch einige Möglichkeiten weg, oder man muss sie anders gestalten.
Wow, dachte die Sache wäre eher Banal, aber das was damit zusammen hängt, ist für mich doch jetzt sehr wichtig, all dies zu wissen.
Danke.

@ mschnell
Das sehe ich etwas anders. Gerade für mein Beispiel an Anfang würde sleep, so wie es früher funktionierte, durchaus Sinn machen. Auch ist in einem alten Buch mittels sleep ein Beispiel-Code, mit dem dann ein beweglicher Kreis dargestellt werden soll. Und sleep ist da nun mal die direkte Methode, mit der alles in einer procedure zusammen gefasst werden kann. Den Ablauf in Hintergrund mal weglassend.
Aber leider auf Grund der Änderungen sollte man es zumindest nicht so ohne weiteres empfehlen.

@ fliegermichel
aua. Da gibt es wohl die Möglichkeit, so weitreichend zu suchen,/arbeiten was die CPU so halt hergibt?


Mit dem ProcessMessages-Befehl ermöglicht man es sogar, dass man noch mal auf den Beispielbutton von mir klicken kann. Dann fängt er von Vorne an, aber wenn er damit fertig ist, macht er das vorherige auch noch fertig.
Tja, so wie es jetzt leider inzwischen ist, ist mir die Anwendung von sleep auch mir nicht mehr so geheuer.
Lazarus 2.2.0 / FP 3.2.4

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: [gelöst] Sleep - Ungewohntes Verhalten?

Beitrag von mschnell »

Erwin hat geschrieben:Und sleep ist da nun mal die direkte Methode, mit der alles in einer procedure zusammen gefasst werden kann. Den Ablauf in Hintergrund mal weglassend.


Wenn man in Lazarus eine "Application" macht, kann man nicht "Den Ablauf in Hintergrund mal weglassen", der ist durch die LCL vorgegeben. Deshalb ist sleep() (im main Thrfead) verboten, weil es eben "Den Ablauf in Hintergrund" massiv stört und dadurch das Verhalten der Application völlig erratisch werden kann.

und fliegermichel sprach von Worker-Threads,. da ist sleep() erlaubt aber Application.ProcessMessages verboten.

-Michael

Erwin
Beiträge: 286
Registriert: Mi 16. Sep 2009, 14:15
OS, Lazarus, FPC: Xubuntu 22.04 / x86_64_linux-gtk 2 / L 2.2.0 / FPC 3.2.2

Re: [gelöst] Sleep - Ungewohntes Verhalten?

Beitrag von Erwin »

Das mit dem Timer ist auch so eine Sache, der wird ja unterbrochen, so bald was anderes im Programm ausgeführt wird. Das finde ich alles andere als Optimal.
Hm... also in alten Büchern zu Delphi las ich es eher so heraus, dass es dann wartet. Also alles andere als den Ablauf Störend ist. Ich ging sogar davon aus, dass man damit (also damals) sogar 2 Buttons machen könnte, und jedes zur anderen Zeit Starten könnte, aber beide dann gleichzeitig ihre Arbeit machen können. Multitasking halt innerhalb eines Programms.
Oder habe ich da einfach zu viel heraus gelesen bzw. rein interpretiert?

Was hat es eigentlich mit dem Zweiten Timer auf sich? TIdleTimer. Der hört sich für mich ja noch brutaler als Sleep an, weil dieser soll sogar den Hauptprozessor anhalten?

Jedenfalls ist das alles für mich jetzt sehr ernüchtern. Ob man damit überhaupt flüssige Grafikanimation mit Interaktion schreiben kann, ohne dass es dann ruckelt?
Lazarus 2.2.0 / FP 3.2.4

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: [gelöst] Sleep - Ungewohntes Verhalten?

Beitrag von mschnell »

Alles kann jederzeit von einem anderen Programm unterbrochen werden.
-Michael

Erwin
Beiträge: 286
Registriert: Mi 16. Sep 2009, 14:15
OS, Lazarus, FPC: Xubuntu 22.04 / x86_64_linux-gtk 2 / L 2.2.0 / FPC 3.2.2

Re: [gelöst] Sleep - Ungewohntes Verhalten?

Beitrag von Erwin »

Also der Application.ProcessMessages-Befehl ist ja sehr wichtig, finde ich. Danke noch mal. Wenn man etwas schreibt, wo ein Zwischenstand ausgegeben werden soll, dann geht dies ja gar nicht ohne den Befehl.

Frage zum Timer: Kann es sein, dass die Zeiteinstellung den Neustart betrifft? Also wenn der Timer ein Intervall von 1000 hat, und er macht etwas, das 200 dauert, kann es sein, dass es dann insgesamt 1200 dauert, bis die nächste Runde des Timers dann startet?
Lazarus 2.2.0 / FP 3.2.4

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2636
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: [gelöst] Sleep - Ungewohntes Verhalten?

Beitrag von m.fuchs »

Erwin hat geschrieben:Frage zum Timer: Kann es sein, dass die Zeiteinstellung den Neustart betrifft? Also wenn der Timer ein Intervall von 1000 hat, und er macht etwas, das 200 dauert, kann es sein, dass es dann insgesamt 1200 dauert, bis die nächste Runde des Timers dann startet?

Nein, er feuert (ungefähr) jede Sekunde. Wenn du dieses Verhalten benötigst, musst du am Anfang der OnTimer-Methode den Timer abschalten und am Ende wieder anschalten.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Erwin
Beiträge: 286
Registriert: Mi 16. Sep 2009, 14:15
OS, Lazarus, FPC: Xubuntu 22.04 / x86_64_linux-gtk 2 / L 2.2.0 / FPC 3.2.2

Re: [gelöst] Sleep - Ungewohntes Verhalten?

Beitrag von Erwin »

Ich glaube, m.fuchs, wir schreiben aneinander vorbei.

Ich habe inzwischen einen Test gemacht. Und war habe ich dem Timer, der auf 10 000 eingestellt war, eine lange Schleife durchlaufen lassen. Bevor er mit der Schleife anfing, angewiesen einem Button als Caption 'Start' zu schreiben. Anschließend habe ich in bis 10 000 zählen lassen, und alles ebenfalls auf dem Button.Caption ausgeben lassen. Und Abschließend Ende. Das dauerte bei mir ca. 5-6 Sekunden.

ich stellte fest, dass nach dem Wort Ende, bis zum Wort Start (bzw. bis zu den nächsten den Zahlen), dann 10 Sekunden vergingen. Und wenn mich nicht alles täuscht, hat er auch am Anfang 10 Sekunden gewartet. Demzufolge ist es doch so, wie ich es vermute habe: Er wartet die Zeit ab, bevor er (wieder) los legt, ungeachtet wie lange er von dem Zeitintervall für die Erledigung der Aufgabe gebraucht hat. Was wiederum bedeutet, wenn er für eine Aufgabe 5 000 braucht, aber er soll die Aufgabe alle 10 000 erledigen, müsste man dann den Timer auf 5 000 einstellen, weil es sonst 15 000 wird (10 000 Wartezeit + 5 000 Arbeitszeit).

Sollte dem nicht so sein, dann muss mein Timer kaputt sein.
Lazarus 2.2.0 / FP 3.2.4

Antworten