Timer / Zeitsteuerung
-
Hi!
Mich interessiert jetzt mal, wie ihr folgende Aufgabe lösen würdet:
Ich möchte alle x Minuten eine Datei auslesen und habe in meinem Programm sowiso schon eine 'Main-Loop'.Würdet ihr:
- je Durchlauf einen Zähler hochsetzen um mit dem sleep-Wert dann auf die entsprechende Zeit zu kommen?
- einen Extra-Thread /-Prozess starten, der dann pollt
- mit einem Timestamp arbeiten
- etwas ganz anderes machen?Begründungen wären auch nett, ich bin halt etwas hin- und her gerissen.
-
würde ein extra thread machen, welchen du alle 500 ms schlafen legst...
-
Ich bin für Lösung D - mit SetTimer() einen Timer anlegen, der nach x Minuten aktiviert wird.
-
Das sind beisdes interessante Varianten, wobei sich die Timer-Variante ersteinmal einfacher anhört, der Thread aber sicher technisch interessanter ist.
Gibt's Gründe für Eure Entscheidung?!
-
Der Unterschied zwischen einem Timer und einem Thread ist, daß bei einem Timer die Hauptschleife steht, d.h. die Timerfunktion wird vollständig ausgeführt, ehe zum Hauptprogramm zurückgesprungen wird, während ein Thread parallel läuft.
Es kommt jetzt darauf an, was du sonst noch in deiner Hauptschleife machst und ob du warten mußt, daß die ganze Datei eingelesen wurde (je nachdem wie groß so eine Datei eben ist)?
-
Naja, das Programm soll halt normal bedienbar sein etc. Nur alle x Minuten soll es (wenn gewünscht) seine Info aktualisieren.
Dass die Hauptschleife steht, bringt dann wohl nichts. Demnach kann ich den Timer nur in einem parallelen Thread einsetzen, um das Aktualisieren zu steuern, richtig? Wo ist dann der Unterschied zu einem Sleep?!
-
Wie lange dauert denn dieses "Daten aktualisieren"? Länger als 1 Sekunde?
Wenn nein dann vergiss den eigenen Thread wieder, ist zu kompliziert und zahlt sich nicht aus.Unterschied Timer/Sleep: ein Timer kann dir z.B. eine Message posten wenn er abgelaufen ist, oder eine Funktion aufrufen wenn er "abgelaufen" ist. Dazwischen kannst du machen was du magst. Sleep blockiert dir dagegen den ganzen Thread bis die Zeit rum ist.
Mit einem Timer kannst du also ganz einfach ohne einen eigenen Thread arbeiten, mit Sleep dagegen eher nicht.
-
Th schrieb:
Der Unterschied zwischen einem Timer und einem Thread ist, daß bei einem Timer die Hauptschleife steht, ...
Ich dachte mir schon, dass ich das dann wohl falsch verstanden habe?!
Das hörte sich für mich so an, als würde mein Programm stehen, solange der Timer läuft - im Prinzip also wie beim Sleep.Die Doku vom Win32-Timer liest sich aber anders. Den werde ich dann wohl mal ausprobieren.
Der Download könnte länger dauern, zumal ich evtl. mehrere Dateien auslese. Das ist aber ersteinmal OK. Aber Du bringst mich damit auf eine Idee zur Version 8.0 (aktuell 0.02 beta :D). da könnte ich dann in einem Extra-Thread die Aktualisierung durchführen.... ersteinmal reicht's auch so. Mal sehen, ob ich den Kram verstehe.
Falls jmd. fertigen Bsp-Code kennt......danke!
-
Er meinte bei Verwendung eines Timers ohne zusätzlichem Thread steht die Hauptschleife *während du das File neu ausliest*.
Deswegen hab' ich auf gefragt wie lange das dauert.
Während der "Wartezeit" steht die Hauptschleife natürlich nicht.
-
hustbaer schrieb:
Er meinte bei Verwendung eines Timers ohne zusätzlichem Thread steht die Hauptschleife *während du das File neu ausliest*.
Deswegen hab' ich auf gefragt wie lange das dauert.
Während der "Wartezeit" steht die Hauptschleife natürlich nicht.Grossartig! So hatte ich's jetzt auch verstanden. Das parallele Auslesen sehe ich mir dann 2009 an :).
-
So, jetzt steh ich aber wieder auf dem Schlauch.
Ich hatt mir die Funktion 'SetTimer' herausgesucht. Aber anscheinend funktioniert die nur ordentlich, wenn man ein Fenster hat. Was mache ich denn, wenn ich keine habe?
Muß ich dann andere Klassen benutzen?Sry, falls ich etwas übersehen habe. Ist wohl schon zu spät....
-
msdn schrieb:
UINT SetTimer( HWND hWnd, UINT nIDEvent, UINT uElapse, TIMERPROC pTimerFunc );
hWnd: Handle to the window to be associated with the timer. This window must be owned by the calling thread. If this parameter is NULL, no window is associated with the timer and the nIDEvent parameter is ignored.
nIDEvent: Specifies a nonzero timer identifier. If the hWnd parameter is NULL, this parameter is ignored.
uElapse: Specifies the time-out value, in milliseconds.
lpTimerFunc: [Long pointer to the function to be notified when the time-out value elapses. For more information about the function, see TimerProc.
If lpTimerFunc is NULL, the system posts a WM_TIMER message to the application queue. The hwnd member of the message’s MSG structure contains the value of the hWnd parameter.msdn schrieb:
void CALLBACK TimerProc( HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime );
hwnd: [in] Handle to the window associated with the timer. wird wahrscheinlich 0 sein
uMsg: [in] Specifies the WM_TIMER message.
idEvent: [in] Identifier of the timer. wird wahrscheinlich 0 sein
dwTime: [in] Specifies the number of milliseconds that have elapsed since the system was started. This is the value returned by the GetTickCount function.
Also geht auch ohne Fenster. Musst bei SetTimer für hWnd NULL einsetzen und lpTimerFunc muss auf eine Funktion zeigen, die wie oben deklariert ist

-
Das bekomme ich so recht nicht auf die Reihe. Auch nicht, durch Lesen der diversen Threads zu dem Thema:
Diese Lösung habe ich gefunden und sie läuft:#include <windows.h> #include <iostream> void CALLBACK TimerProc (HWND hwnd, UINT message, UINT TimerID, DWORD dwTime) { std::cout << "hello timer" << std::endl; } int main() { SetTimer(NULL, 1, 1000,(TIMERPROC) TimerProc); MessageBox (NULL, "muss sein, sonst hat dein proggi keine message queue", "", MB_OK); }- Das ist MIT Fenster und MIT Callback, korrekt?
Wie sähe die Lösung ohne Callback aus?
Und wichtiger: wie die Funktion ohne Fenster? Ich bekomm's auch nicht hin eine Messagequeue selbst zu erstellen (was vielleicht auch an 'nebenbei liegt', s.u.).
Nebenbei: Wenn ich in einer Loop auf den Timer warten muss, dann ist das etwas blöd, weil ich 'meine Main-Loop' bereits für das Update eines Peripheriegeräts brauche und das nur ungern vermischen möchte.
------
Sry, falls ich mich blöd anstelle, hatte gehofft, dass etwas Schlaf hilft...
-
Die lösung ist ohne fenster (Hwnd NULL)!!
die funktion :
void CALLBACK TimerProc (HWND hwnd, UINT message, UINT TimerID, DWORD dwTime) { std::cout << "hello timer" << std::endl; }wird nun jede sekundne ausgeführt, darin kannst du deine datei lesen...
-
BorisDieKlinge schrieb:
(Hwnd NULL)!!
Ähhmmm.... das ist doch aber NULL!
SetTimer([b]NULL[/b], 1, 1000,(TIMERPROC) TimerProc);Oder welches Handle ist gemeint?
btw: seeeehr schnelle Antwort, wow - ich muss jetzt erstmal frühstücken, aber dann bin ich wieder da

-
Erste Parameter von "SetTimer(HWND hWnd,.....)" -< wenn der NULL ist, dann OHNE Fenster... Die löung dürfe also für deine Ansprüche KORREKT sein
-
Hab grad keine Lust zu gucken, warum das mit der TimerProc nicht funktioniert (na gut, Message-Queue fehlt).
Jedenfalls, Message-Queue geht so:MSG Msg; while ( GetMessage( &Msg, NULL, 0, 0 ) ) { TranslateMessage( &Msg ); DispatchMessage( &Msg ); }Kommst aber halt so nicht aus der Message-Queue raus, ohne Fenster und so. Außer du benutzt PeekMessage statt GetMessage, baust eine Zeitabfrage rein und ein kleines Sleep.
Eine andere Lösung ist timeSetEvent, da kannst du eine Menge Parameter angeben, z.B. brauchst du auch keinen Message-Queue.
#include <mmsystem.h> #pragma comment( lib, "Winmm.lib" ) // oder die lib einfach so angeben void CALLBACK TimerProc( UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) { } ... MMRESULT r = timeSetEvent( 1000, 1, TimerProc, 0, TIME_PERIODIC|TIME_CALLBACK_FUNCTION|TIME_KILL_SYNCHRONOUS ); ... timeKillEvent( r );
-
BorisDieKlinge schrieb:
Erste Parameter von "SetTimer(HWND hWnd,.....)" -< wenn der NULL ist, dann OHNE Fenster... Die löung dürfe also für deine Ansprüche KORREKT sein
Das habe ich doch aber probiert, mit meinem Bsp-Code, habe nur die MessageBox weggelassen. Aber dann bleibt die Konsole leer, keine Ausgaben.
@badestarnd: das sehe ich mir nachher mal an.
-
MSDN - SetTimer schrieb:
An application can process WM_TIMER messages by including a WM_TIMER case statement in the window procedure or by specifying a TimerProc callback function when creating the timer. When you specify a TimerProc callback function, the default window procedure calls the callback function when it processes WM_TIMER. Therefore, you need to dispatch messages in the calling thread, even when you use TimerProc instead of processing WM_TIMER.
Auf gut Deutsch - SetTimer funktioniert nur auf Grundlage einer bestehenden Message-Queue (d.h. in einem WinAPI-Programm).
-
So, an dieser Stelle ersteinmal DANKE an alle, die mir helfen!
...und jetzt weiter im Text:
SetTimer ist also nichts.
timeSetEvent könnte klappen, das teste ich gleich mal. Laut MSDN läuft der Timer dann aber in einem eigenen Thread, wenn ich später mal das Aktualisieren meiner Daten in einem eigenen Thread machen möchte, dann wäre ich damit schon bei 3 Threads.... wäre es in em Fall dann sinnvoller, den 2 Thread zu starten in statt timeSetEvent einfach mit einem Sleep zu arbeiten? Oder ist Sleep inperformant?Eine ganz andere Variante ist an dieser Stelle ja das Arbeiten mit Timestamp (wie auch immer das genau aussieht), damit meine ich, ich definiere den Zeitpunkt der nächsten Aktualisierung und prüfe in meiner Schleife, ob die Systemzeit diesen Zeitpunkt überschritten hat (das Update also stattfinden muß).
Wie sieht's damit aus? Gibt es Gründe (Performance), warum timeSetEvent vorzuziehen ist?