Alternative Möglichkeit für GetTickCount?



  • Hallo zusammen,
    ich möchte in meinem Programm auswerten wie lange keine Maus und Tastaturinputs erfolgten. Dies geschieht ja in alt bekannter Manier:

    void __fastcall TForm1::Timeout1Timer(TObject *Sender)
    {
    
    	 LASTINPUTINFO last_input;
    	 last_input.cbSize = sizeof(LASTINPUTINFO);
    
    	 GetLastInputInfo(&last_input);
    	 DWORD time_elapsed = GetTickCount();
    
    	 int timeout_time = (time_elapsed - last_input.dwTime) / 1000;
    
    ...
    .........
    }
    

    Das Problem an der ganze Sache ist das der Rechner definitiv länger als 49 Tage läuft und somit GetTickCount wieder auf 0 springt. Hat jemand von euch eine Idee wie man das lösen könnte?



  • Sind auch die gemessenen Intervalle größer als 49 Tage? Falls nein, dann ist doch alles ok.



  • Der Timer pollt im Sekundentakt, meinst du das?



  • Zero01 schrieb:

    Der Timer pollt im Sekundentakt, meinst du das?

    Ich meine, beim Überlauf passiert nix schlimmes wegen des Überlaufs beim Subtrahieren, der gleicht das wieder aus.

    Beispiel gerade nach gut 49 Tagen:

    Start=4294967286 //2^32-10
    Ende=20 //also 30ms später

    Du rechnest Ende-Start=20-4294967286=30. Richtig.

    Das knirscht erst, wenn Zwischen Start und Ende mehr als ein ganzer Durchlauf von 49 Tagen liegt. Ah, bei Dir liegt nir viel mehr als eine Sekunde daziwchen, weil Du sekündlich pollst? Dann kann gar nix passieren.

    edit: halt, ich sehe int bei Dir. Ich gehe nur von unsigned aus. Da bin ich sicherer, daß das Rechnen klappt.



  • *popcornholengeh*



  • als unsigned sind die integer alle positiv + freigewordenes steuerbit = 31 + 1, also voll 32 bit Positiv.

    Was ich nicht in die Birne bekomme ist das der Tickcount ja in Millisekunden seit Systemstart auflöst und nach 49 Tagen genullt wird. Dies ist doch unabhängig davon wie ich polle



  • Ach klar, falls Start z.B 2^32 + 100 (mehr als 49 Tage nach dem letzten Input) und Ende 2^32 -10 (gettickcount) ist, stimmt die Zeitmessung logisch nicht mehr, ist aber rein mathematisch korrekt. D.h. wenn innerhalb von 49 Tagen Start 2^32 - X ist stimmt die Berechnung logisch. Die erste Berechnung wäre dann logisch falsch, aber die weitere würde dann wieder passen.

    Auf gut Deutsch: solange innerhalb von 49 Tagen jemand Maus und Tastatur bewegt passiert nichts.

    GetLastInputInfo(&last_input);
    	 DWORD time_elapsed = GetTickCount();
    
    	 unsigned int timeout_time = (time_elapsed - last_input.dwTime) / 1000;
    

    Korrekt?



  • Wofür willst deine errechnete timeout_time denn verwenden?



  • LASTINPUTINFO last_input;
    	 last_input.cbSize = sizeof(LASTINPUTINFO);
    	 GetLastInputInfo(&last_input);
    	 DWORD time_elapsed = GetTickCount();
    
    	 unsigned int timeout_time = (time_elapsed - last_input.dwTime) / 1000;
         Edit2->Text = timeout_time;
    
    	 if (timeout_time > 180)
    	{
    		  try
    		{
    			  if(WebBrowser1->LocationURL.Pos("https://xxxxxx.de/login=") == 1)
    			  WebBrowser1->Navigate("https://xxxxxxx.de/index/logout?");
    ...
    .......
    

    Falls innerhalb von 3 Minuten keine Eingaben kommen soll der angemeldete User automatisch aus unserem Webterminal abgemeldet werden falls er dies vergessen hat und gegangen ist.



  • Ups, das Edit2->Text war nur zum testen gedacht....

    Edit: Natürlich ist dies auch nur ein eine Quick and Dirty Version zum testen. Syntaktisch und logisch geht da mehr 😋



  • Zero01 schrieb:

    Auf gut Deutsch: solange innerhalb von 49 Tagen jemand Maus und Tastatur bewegt passiert nichts.

    Hat mich stutzen lassen. Es passiert nämlich bei 3 Minuten nie etwas Falsches.



  • Stimmt, war ebanfalls ein Denkfehler von mir da GetLastInputInfo(&var) GetTickCount gleichgesetzt wird sobald ein Input kommt. Sonst könnte man ja keine zueinander abhängige Differenz errechnen. Ich saß diese Woche locker 60h vorm Compiler - ein Spaziergang an der frischen Luft zwischendurch würde so Themen wie diese glaube vermeiden 😉 Mittwoch ist Vorstellung der Beta.

    Ich danke euch vielmals!



  • Wenn der Wraparound tatsächlich mal ein Problem darstellen sollte, gibt es ja noch GetTickCount64().



  • Danke Audacia, diese Variante hatte ich mir auch angesehen

    Edit: im Post zu vor hatte ich mich etwas unklar ausgedruckt. GetTickCount und GetLastInputInfo beziehen ihre Zeit vom gleichen Timer, werden also sobald ein Input erfolgt logisch gleichgesetzt mit einer zu vernachlässigenden Verzögerung und dann fängt die eigentliche Zeitmessung an. Egal ob Wrap oder nicht, da es nur 3 min zu messen gilt kann nie etwas passieren. Die Variablen einschliesslich DWORD sind unsigned Variablen so das die Berechnung immer mit positiven Ganzzahlen rechnet.

    Ich hatte anfangs einen Lösungsweg über die Window Messages die Zeit zu stoppen aber ich wollte diesen eh ein wenig kritischen Eventhandler nicht dafür vergewaltigen.

    GetTickCount auf Serverebene ist der Grund warum dies zu dem besagten Thema führt. Möchte man Messungen machen die im Intervall klar über 2^32 hinausgehen bleibt einem nichts anderes übrig als den Wrap zu erkennen und entsprechend den Überhang anhand von Hilfsvariablen zu berechnen. Sicherlich gibt es dafür sehr schöne Lösungen.



  • Ich benutze für solch "grosse" Zeitdifferenzen immer TDateTime. Und für welche, die im ms Bereich liegen, QueryPerformanceCounter (in Verbindung mit QueryPerformanceFrequency)


Anmelden zum Antworten