AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi TTimer und Abarbeitung der Messages
Thema durchsuchen
Ansicht
Themen-Optionen

TTimer und Abarbeitung der Messages

Ein Thema von Blamaster · begonnen am 13. Okt 2014 · letzter Beitrag vom 14. Okt 2014
Antwort Antwort
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#1

AW: TTimer und Abarbeitung der Messages

  Alt 13. Okt 2014, 18:36
Warum nimmst du einen Timer und nicht Delphi-Referenz durchsuchenTApplicationEvents.OnIdle? Würde hier besser passen.

Und ein Assigned verbunden mit einem FreeAndNil wirkt Wunder
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Blamaster

Registriert seit: 20. Jul 2007
230 Beiträge
 
#2

AW: TTimer und Abarbeitung der Messages

  Alt 13. Okt 2014, 19:23
Hi,

vielen Dank für die schnellen Antworten

Der Weg über FreeAndNil() inkl Assigned() Prüfung ist mir bekannt. Allerdings ging es mit primär darum zu verstehen wie und wann die Window Messages abgerarbeitet werden das muss doch in irgendeiner Form deterministisch sein. Ich war immer der Auffassung das Messages im Gegensatz zu Threads nicht den Programmfluss unterbrechen und daher im Gegensatz zu Threads auch keine Synchronisation benötigen.

Desweiteren kommt mir die Nutzbarkeit des TTimer etwas arge eingeschränkt vor wenn man sich nicht darauf verlassen kann das nach einem .Enable := False; auch keine Events mehr ausgelöst werden.

Der Tipp mit dem IdleEvent ist super das muss ich mir merken

Nochmal zum TTimer:

Delphi-Quellcode:
procedure TTimer.SetEnabled(Value: Boolean);
begin
  if Value <> FEnabled then
  begin
    FEnabled := Value;
    UpdateTimer;
  end;
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.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;
Das obige ist der Originalcode aus der ExtCtrls.pas würde ich mit folgender Änderung erreichen können das nach dem Disable wirklich keine Events mehr ausgelöst werden ? (oder übersehe ich da was ?)

Delphi-Quellcode:
procedure TTimer.WndProc(var Msg: TMessage);
begin
  with Msg do
    if Msg = WM_TIMER then
      try
        if FEnabled then Timer; // FEnable check to avoid Events after disable
      except
        Application.HandleException(Self);
      end
    else
      Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam);
end;
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.556 Beiträge
 
Delphi 12 Athens
 
#3

AW: TTimer und Abarbeitung der Messages

  Alt 13. Okt 2014, 19:56
Zitat:
t vor wenn man sich nicht darauf verlassen kann das nach einem .Enable := False; auch keine Events mehr ausgelöst werden.
Darauf kann man sich doch auch verlassen.

Wenn der Timer Disabled wird, dann wird sofort MSDN-Library durchsuchenKillTimer aufgerufen und damit werden auch alle TimerEvents aus der MessageQueue entfernt, womit auch kein WM_TIMER mehr eintreffen kann.

[add]
Und da man auf solche Komponenten niemals aus anderen Threads zugreift, kann es auch nicht zu Problemen kommen.
Auch nicht bezüglich des nachfolgend genannten Timer.OnTimer := nil , denn auch dabei wird sofort KillTimer aufgerufen.
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (13. Okt 2014 um 20:07 Uhr)
  Mit Zitat antworten Zitat
mm1256

Registriert seit: 10. Feb 2014
Ort: Wackersdorf, Bayern
642 Beiträge
 
Delphi 10.1 Berlin Professional
 
#4

AW: TTimer und Abarbeitung der Messages

  Alt 13. Okt 2014, 20:02
Und warum nicht einfach zuerst

Timer.OnTimer := nil

und dann erst

Timer.Enabled := false;

dann kann doch eigentlich nichts mehr passieren, oder?
  Mit Zitat antworten Zitat
Blamaster

Registriert seit: 20. Jul 2007
230 Beiträge
 
#5

AW: TTimer und Abarbeitung der Messages

  Alt 13. Okt 2014, 20:07
@himitsu
Genau das hätte ich für logisch empfunden.

Zitat aus der Windows Api
Zitat:
The KillTimer function does not remove WM_TIMER messages already posted to the message queue.
Sprich Messages die kurz vor dem Enable := false ankamen werden halt doch weiter verarbeitet und somit ist es durchaus realistisch das bei ungünstigem "scheduling" ein Event nach dem dsiable auftritt.

@mm1256
So sollte es natürlich auch klappen und man muss dafür das TTimer Objekt nicht anpassen perfekt.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.556 Beiträge
 
Delphi 12 Athens
 
#6

AW: TTimer und Abarbeitung der Messages

  Alt 13. Okt 2014, 20:39
Bist du sicher, daß die Hilfe da stimmt?

Ich kann mich nicht erinnern jemals ein TimerEvent nach dem deaktivieren eines Timers bekommen zu haben.
Da wäre es doch statistisch eigenartig, wenn das niemals passiert wäre.


Hab mal schnell einen Test gemacht:
> zwei Timer und Memo auf der Form

Delphi-Quellcode:
procedure TForm2.FormCreate(Sender: TObject);
begin
  Timer1.Interval := 500;
  Timer2.Interval := 5000;
end;

procedure TForm2.Timer1Timer(Sender: TObject);
begin
  Memo1.Tag := Memo1.Tag + 1;
  Memo1.Lines.Add('OnTimer: ' + IntToStr(Memo1.Tag));
end;

procedure TForm2.Timer2Timer(Sender: TObject);
begin
  Timer2.Enabled := False;

  Memo1.Lines.Add('Disable 1');
  //Timer1.Enabled := False; // disablen vor dem Event
  Sleep(1500);
  Timer1.Enabled := False; // disablen nach dem Event
  Memo1.Lines.Add('Disable 2');
end;
Delphi-Quellcode:
procedure TForm2.FormCreate(Sender: TObject);
begin
  Timer1.Interval := 500;
  Timer2.Enabled := False;
end;

procedure TForm2.Timer1Timer(Sender: TObject);
begin
  Memo1.Lines.Add('OnTimer');
  Sleep(1500);
  Memo1.Lines.Add('Disable');
  Timer1.Enabled := False;
end;

procedure TForm2.Timer2Timer(Sender: TObject);
begin
  //
end;
In beiden Fällen müsste dann ein OnTimer eintreffen, nachdem der Timer deaktiviert wurde, aber es passiert nicht.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.556 Beiträge
 
Delphi 12 Athens
 
#7

AW: TTimer und Abarbeitung der Messages

  Alt 13. Okt 2014, 20:54
Wenn ich manuell was in die Queue schiebe, dann wird das nicht verworfen.
Sehr verwirrend.

Delphi-Quellcode:
type
  THackedTimer = class(TComponent)
  private
    FInterval: Cardinal;
    FWindowHandle: HWND;
  end;

procedure TForm2.FormCreate(Sender: TObject);
begin
  Timer1.Interval := 500;
  Timer2.Enabled := False;
end;

procedure TForm2.Timer1Timer(Sender: TObject);
begin
  Memo1.Lines.Add('OnTimer');

  if THackedTimer(Timer1).FInterval = 0 then ;
  PostMessage(THackedTimer(Timer1).FWindowHandle, WM_TIMER, 1, 0);

  Sleep(1500);
  Memo1.Lines.Add('Disable');
  Timer1.Enabled := False;
end;

procedure TForm2.Timer2Timer(Sender: TObject);
begin
  //
end;
Ich dachte Windows schiebt die Timer-Events asynchron in die Queue.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:05 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz