Autor |
Beitrag |
Daniel L.
      
Beiträge: 140
Erhaltene Danke: 14
W7, W8
TurboD Prof, Delphi Community
|
Verfasst: Sa 15.12.12 12:12
Hallo
Angenommen, ein Timerintervall ist kleiner als die Zeit, die der durch das OnTimer-Ereigniss auszuführende Code braucht -- landen dann die Ereigniss in einer Warteschleife, um sie nach und nach abzuarbeiten, was ja dann irgenwann zu einem Überlauf führen müsste --
oder wird ein Timerereigniss nur dann "ausgesendet", wenn die Anwengung "nichst zu tun hat"?
In meiner Anwednugn werden langwierige Zeichnungen durch Timerimpulse ausgeführt (Canvas),
und ich will sicher stellen, dass es nicht zu einem wie oben beschriebenen Problem führen kann.
Die Anwendug soll ja auch auf langsameren Rechnern laufen können.
Danke schon mal und Gruss: Daniel Moderiert von Narses: Topic aus Delphi Language (Object-Pascal) / CLX verschoben am Sa 15.12.2012 um 19:42
|
|
Mathematiker
      
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Sa 15.12.12 12:40
Hallo,
die nächste Ausführung der Timer-Methode erfolgt erst, wenn die vorhergehende beendet wurde.
Ich kenne diesen Effekt auf meinem alten Computer sehr gut. Gleichgültig, wie klein man das Timer-Interval wählt, ausgeführt wird die Routine erst, wenn die Berechnung/Darstellung wieder möglich ist.
Beste Grüße
Mathematiker
_________________ Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
|
|
WasWeißDennIch
      
Beiträge: 653
Erhaltene Danke: 160
|
Verfasst: Sa 15.12.12 13:22
Da der TTimer die WM_TIMER-Message verwendet, landen diese in der Messagequeue. Ob die nun irgendwann "überläuft" kann ich magels Erfahrung gar nicht sagen, aber man könnte ja Vorsorge treffen, indem man den Timer im OnTimer-Event anhält, abarbeitet und wieder startet. Die Genauigkeit leidet natürlich etwas darunter, aber erstens hat die WM_TIMER-Message nur untergeordnete Priorität und zweitens ist diese Genauigkeit eh nicht gegeben, wenn die Abarbeitung zu lange dauert.
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: Sa 15.12.12 20:42
Moin!
WasWeißDennIch hat folgendes geschrieben : | Da der TTimer die WM_TIMER-Message verwendet, landen diese in der Messagequeue. |
AFAIR wird der WinAPI-Timer immer wieder neu nach einem Ereignis aufgesetzt, so dass keine Ereignisse in irgendeiner Queue landen.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
WasWeißDennIch
      
Beiträge: 653
Erhaltene Danke: 160
|
Verfasst: Sa 15.12.12 21:20
Ich habe gerade im MSDN WM_TIMER, SetTimer und TimerProc durchforstet, konnte aber nichts dergleichen entdecken. Woher hast Du diese Info?
|
|
Tilman
      
Beiträge: 1405
Erhaltene Danke: 51
Win 7, Android
Turbo Delphi, Eclipse
|
Verfasst: Sa 15.12.12 21:29
Einloggen, um Attachments anzusehen!
_________________ Bringe einen Menschen zum grübeln, dann kannst du heimlich seinen Reis essen.
(Koreanisches Sprichwort)
|
|
Mathematiker
      
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Sa 15.12.12 22:35
Hallo Tilman,
Tilman hat folgendes geschrieben : | Mathematiker hat folgendes geschrieben : | Hallo,
die nächste Ausführung der Timer-Methode erfolgt erst, wenn die vorhergehende beendet wurde. |
Leider nein, wie man leicht mit einer ShowMessage feststellen kann: |
Tut mir leid, Dein Gegenbeispiel funktioniert nur durch das Einfügen von Showmessage. Ich habe es mit
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| procedure TForm1.Timer1Timer(Sender: TObject); var x,y:real; i,zufall: Integer; begin zufall := random(100); listbox1.items.add('start '+IntToStr(zufall)); x:=pi/2; y:=0; for i:=1 to 10000000 do begin y:=sin(x)+cos(x); x:=y; end; listbox1.items.add('fertig '+IntToStr(zufall)); if listbox1.items.count>10 then begin timer1.enabled:=false; listbox1.items.add(inttostr(gettickcount-zeit)); end; end; |
ausprobiert und trotz timer.iterval=1 und wesentlich längerer Berechnungszeit als 1 ms, werden die start- und fertig-Werte korrekt hintereinander ausgegeben. Für die 6 Timer-Aufrufe brauchte mein Computer 19 Sekunden!
Ich vermute, dass nach einem Aufruf von showmessage eine Art application.processmessages gerufen wird; sonst würden ja alle anderen Prozesse "stehen" bis man OK gedrückt hat. Dadurch wird auch ein neues Starten der Timer-Methode möglich.
Enthält die Timer-Methode keinen derartigen Code, dürfte meine Aussage korrekt sein.
Beste Grüße
Mathematiker
_________________ Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
|
|
WasWeißDennIch
      
Beiträge: 653
Erhaltene Danke: 160
|
Verfasst: Sa 15.12.12 22:55
Wieso sollten andere Prozesse stehen, bis man OK klickt? Ich kann Dir da nicht folgen.
|
|
Narses
      

Beiträge: 10183
Erhaltene Danke: 1256
W10ent
TP3 .. D7pro .. D10.2CE
|
Verfasst: So 16.12.12 00:16
Moin!
WasWeißDennIch hat folgendes geschrieben : | Ich habe gerade im MSDN WM_TIMER, SetTimer und TimerProc durchforstet, konnte aber nichts dergleichen entdecken. Woher hast Du diese Info? |
Aus dem VCL-Source.  Allerdings hab ich mich wohl doch eher an Quatsch erinnert  denn es ist tatsächlich so:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49:
| procedure TTimer.WndProc(var Msg: TMessage); begin with Msg do if Msg = WM_TIMER then try Timer; except Application.HandleException(Self); end else Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam); end;
procedure TTimer.UpdateTimer; begin KillTimer(FWindowHandle, 1); if (FInterval <> 0) and FEnabled and Assigned(FOnTimer) then if SetTimer(FWindowHandle, 1, FInterval, nil) = 0 then raise EOutOfResources.Create(SNoTimers); end;
procedure TTimer.SetEnabled(Value: Boolean); begin if Value <> FEnabled then begin FEnabled := Value; UpdateTimer; end; end;
procedure TTimer.SetInterval(Value: Cardinal); begin if Value <> FInterval then begin FInterval := Value; UpdateTimer; end; end;
procedure TTimer.SetOnTimer(Value: TNotifyEvent); begin FOnTimer := Value; UpdateTimer; end;
procedure TTimer.Timer; begin if Assigned(FOnTimer) then FOnTimer(Self); end; |
Das erklärt allerdings nicht das Verhalten, dass man beobachten kann ggü. der Erwartung, dass Timermessages die MessageQueue "überfluten" sollten, wenn der Timer-Messagehandler sehr lange braucht. Scheint, als würde die API erst die nächste WM_TIMER-Message absetzen, wenn die WndProc das Ende der vorausgegangenen "gemeldet" hat.  Das würde zumindest das beobachtete Verhalten erklären.  MSDN sagt leider nix dazu...
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: So 16.12.12 02:47
Dazu muss man wissen, dass es intern mehrere Typen von Timern gibt (Oneshot-Timer, die nach Ausführung warten bis sie erneut gesetzt werden, RIT-Timer, die direkt wieder ausgeführt werden, egal was passiert, und normale Timer, die nach Ausführung auf ausführbar gesetzt werden).
Bei den Timern, um die es hier geht, wird das Flag beim Versuch den Timer auszuführen geprüft. (Wie prinzipiell auch bei den anderen.) Nur, wenn der Timer gerade bereit ist, also nicht ausgeführt wird, wird er erneut ausgeführt.
Narses hat das auch am Ergebnis schon korrekt beschrieben.
Ein wenig zur Funktionsweise findet man hier:
www.reactos.freedoor...in32k/ntuser/timer.c
Auch wenn das auf den ersten Blick intern anders umgesetzt ist als in Microsoft Windows soweit ich das weiß.
|
|
|