Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Timer ohne VCL (https://www.delphipraxis.net/134852-timer-ohne-vcl.html)

Mr_G 30. Mai 2009 17:58


Timer ohne VCL
 
Hallo zusammen,
ich Suche eine Möglichkeit in einem Thread auf einen bestimmten Zeitpunkt zu warten. Meine Idee war nun die Differenz zwischen dem aktuellen und dem Zielzeitpunkt zu berechnen und dann zu warten.
Meine Frage: Wie mach ich das nun am besten?
Eine Möglichkeit die ich gefunden habe wäre ein WaitForSingleObject mit dem entsprechenden Intervall, doch ich frage mich ob es dort nicht zu größeren Abweichungen kommen kann.

quendolineDD 30. Mai 2009 18:13

Re: Timer ohne VCL
 
Was denn für einen bestimmten Zeitpunkt?

Apollonius 30. Mai 2009 18:17

Re: Timer ohne VCL
 
Bei WaitForSingleObject sollte es eigentlich nicht zu größeren Abweichungen kommen, ist aber letztlich auch nicht genauer als Sleep.
Die normale Variante verwendet Waitable-Timer-Objekte. Du kannst zum Beispiel sagen, dass ein Waitable Timer zu einem bestimmten Zeitpunkt (absolut) oder nach einer bestimmten Zeit (relativ) signalisiert werden soll. Auf den Timer kannst du dann mit einer beliebigen Wait Function warten.

Mr_G 30. Mai 2009 18:34

Re: Timer ohne VCL
 
Waitable-Timer-Objekte... ich glaube, dass war das Stichwort, was ich gesucht habe!
Vielen Dank!

Mr_G 31. Mai 2009 12:06

Re: Timer ohne VCL
 
Ich habe nun mal ein bisschen mit diesen Waitable-Timer-Objects rumgespielt. Leider verstehe ich das mit dem APC-Callback nicht. Dieser wird bei mir nicht ausgelöst:
Delphi-Quellcode:
procedure Trigger(lpArgToCompletionRoutine: Pointer; dwTimerLowValue, dwTimerHighValue: DWORD);
begin
  ShowMessage('Callback...');
end;

procedure TForm1.Button1Click(Sender: TObject);
var Wecker: SYSTEMTIME;
    CorrectTriggerTime, TriggerTime: FILETIME;
    DueTime: LARGE_INTEGER;
begin
  GetLocalTime(Wecker);
  Wecker.wMinute := Wecker.wMinute +1;
  SystemTimeToFileTime(Wecker, TriggerTime);
  LocalFileTimeToFileTime(TriggerTime, CorrectTriggerTime);
  DueTime.LowPart := CorrectTriggerTime.dwLowDateTime;
  DueTime.HighPart := CorrectTriggerTime.dwHighDateTime;

  SetWaitableTimer(WndTimer, DueTime.QuadPart, 0, @Trigger, nil, True);
  WaitForSingleObjectEx(WndTimer, INFINITE, True);
  Showmessage('Schluss');
end;
Bei dem Test wird wie gewünscht eine Minute gewartet, der der Callback wird aber nicht aufgerufen. Das mit den APCs durchschaue ich im Moment leider nicht. Ich würde mich freuen, wenn mir jemand auf die Sprünge helfen könnte!

Apollonius 31. Mai 2009 12:16

Re: Timer ohne VCL
 
Du hast bei den Waitable Timern zwei verschiedene Möglichkeiten: Entweder du wartest auf das Objekt, oder du lässt dich per APC benachrichtigen. Du vermischst hier beides. Dabei passiert folgendes: Wenn der Timer ausgelöst wird, wird zunächst dein Thread aus dem WaitForSingleObjectEx "befreit"; danach wird die APC in die Warteschlange deines Threads gesetzt. Der Thread ist jedoch schon wieder bereit zum Weiterlaufen und hat damit den Zustand, in dem er APCs verarbeiten kann, verlassen.
Du solltest dich jetzt entscheiden: Wenn du WaitForSingleObjectEx verwendest, brauchst du APCs nicht, da du ja direkt erfährst, wann der Timer ausgelöst wurde; wenn du APCs verwendest, brauchst du WaitForSingleObjectEx nicht, sondern musst nur periodisch in den "alertable wait state" gehen, z.B. mit SleepEx.

himitsu 31. Mai 2009 12:25

Re: Timer ohne VCL
 
und bist'e dir mit der Aufrufkonvention für dein Trigger ganz sicher? (ich hätte da jetzt ein stdcall erwartet)

aber so wie der Code in #5 ist, würde da auch ein Sleep ausreichen.

PS: der Trigger ist da, damit der Thread weiterlaufen kann und bei Ablauf der Zeit benachrichtigt wird.

Mr_G 31. Mai 2009 12:49

Re: Timer ohne VCL
 
Zitat:

Zitat von himitsu
und bist'e dir mit der Aufrufkonvention für dein Trigger ganz sicher? (ich hätte da jetzt ein stdcall erwartet)

Du hast natürlich Recht...
Zitat:

Zitat von himitsu
PS: der Trigger ist da, damit der Thread weiterlaufen kann und bei Ablauf der Zeit benachrichtigt wird.

Wie meinen?

Apollonius 31. Mai 2009 12:51

Re: Timer ohne VCL
 
APCs sind dazu da, damit du WaitForSingleObjectEx nicht brauchst.

Mr_G 31. Mai 2009 12:59

Re: Timer ohne VCL
 
Tjo... nur kommt das nicht am Ende aufs gleiche raus? Bei dem einen muss ich ab und an mit WaitForSingleObject nachfragen und bei den APCs muss ich mit SleepEx auch ab und zu die Gelegenheit geben den Callback auszuführen.

Apollonius 31. Mai 2009 13:04

Re: Timer ohne VCL
 
In deinem Fall würde ich auf APCs verzichten und lieber mit WaitForSingleObject warten. Aber APCs sind sehr nützlich, wenn du viele Timer hast, weil du dann nicht ein Array von Handles brauchst, auf das du wartest und dir dann auch noch merken musst, was du beim Signalisieren ausführen musst.

himitsu 31. Mai 2009 13:07

Re: Timer ohne VCL
 
drum sagte ich ja ... wenn eh gewartet werden soll, warum dann nicht einfach nur Sleep bzw. SleepEx, falls es auch vor der Zeit abbrechbar sein soll?
Delphi-Quellcode:
Sleep(1*60*1000);

Mr_G 31. Mai 2009 13:10

Re: Timer ohne VCL
 
Interessante Sache diese APCs... vielen Dank für die Hilfe! :dp:

@himitsu: Es geht da z.T. um größere Zeiträume (Tage bis Wochen) und ich meine gelesen zu haben, dass Sleep da nicht so genau ist.

himitsu 31. Mai 2009 13:32

Re: Timer ohne VCL
 
je größer der Zeitraum, desto genauer wird Sleep

MSDN (SleepEx)
If dwMilliseconds is less than the resolution of the system clock, the thread may sleep for less than the specified length of time. If dwMilliseconds is greater than one tick but less than two, the wait can be anywhere between one and two ticks, and so on.

Mr_G 31. Mai 2009 14:07

Re: Timer ohne VCL
 
Oje... ist es dann völlig Wurst was ich nehme, oder gibt es hier und da noch Vor- und Nachteile?

quendolineDD 31. Mai 2009 14:16

Re: Timer ohne VCL
 
Siehe Beitrag #11.

Mr_G 31. Mai 2009 14:38

Re: Timer ohne VCL
 
Die Frage ist ja Sleep vs. Waitable-Timer... Bei Sleep denke ich ist das beenden unangenehmer... daher bleib ich bei den Timer-Viechern :)

Apollonius 31. Mai 2009 15:01

Re: Timer ohne VCL
 
Du könntest auch SleepEx nehmen und zum Beenden einen APC schicken.


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:01 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz