Autor Beitrag
Daniel L.
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 140
Erhaltene Danke: 14

W7, W8
TurboD Prof, Delphi Community
BeitragVerfasst: 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 user profile iconNarses: Topic aus Delphi Language (Object-Pascal) / CLX verschoben am Sa 15.12.2012 um 19:42
Mathematiker
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Sa 15.12.12 20:42 
Moin!

user profile iconWasWeißDennIch hat folgendes geschrieben Zum zitierten Posting springen:
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. :idea:

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
WasWeißDennIch
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1405
Erhaltene Danke: 51

Win 7, Android
Turbo Delphi, Eclipse
BeitragVerfasst: Sa 15.12.12 21:29 
user profile iconMathematiker hat folgendes geschrieben Zum zitierten Posting springen:
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:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure TForm1.Timer1Timer(Sender: TObject);
  var zufall: Integer;
begin
  zufall := random(100);
  writeln('start '+IntToStr(zufall));
  showmessage('Unterbrechung');
  writeln ('fertig '+IntToStr(zufall));
end;


//Edit: Bild hinzugefügt
unterbrechung
Einloggen, um Attachments anzusehen!
_________________
Bringe einen Menschen zum grübeln, dann kannst du heimlich seinen Reis essen.
(Koreanisches Sprichwort)
Mathematiker
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Sa 15.12.12 22:35 
Hallo Tilman,
user profile iconTilman hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconMathematiker hat folgendes geschrieben Zum zitierten Posting springen:
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
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 653
Erhaltene Danke: 160



BeitragVerfasst: Sa 15.12.12 22:55 
Wieso sollten andere Prozesse stehen, bis man OK klickt? Ich kann Dir da nicht folgen.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: So 16.12.12 00:16 
Moin!

user profile iconWasWeißDennIch hat folgendes geschrieben Zum zitierten Posting springen:
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:
ausblenden volle Höhe Delphi-Quelltext
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 <> 0and 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. :idea: Das würde zumindest das beobachtete Verhalten erklären. :nixweiss: MSDN sagt leider nix dazu... :les: :lupe: :gruebel:

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: 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.

user profile iconNarses 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ß.