Alle 5 Minuten Aktion



  • Pferdi schrieb:

    Danke Icematix!
    Naja aber, es soll so sein, dass es zu jeder fünften Minute der Stunde ausgeführt wird. Also z.B. um 15.55, 20.10...

    Dann wartest du eben immer bis zum nächsten Fünfer.

    Um die aktuelle Zeit rauszufinden:
    http://www.cplusplus.com/reference/clibrary/ctime/time/
    http://www.cplusplus.com/reference/clibrary/ctime/localtime/



  • Hat dein Programm einen bestimmten State, der alle 5 Minuten angepasst wird und der keinesfalls verloren gehen darf und vor allem recht rechenintensiv ist, um ihn wieder her zu stellen, oder geht es echt nur darum alle 5 Minuten z.B. eine Log-Datei nach Fehlern zu durchsuchen und in ne Datenbank zu schreiben oder Mails auf dem lokalen Mailserver abzuholen, oder ...

    Falls ersteres musst du halt die aktuelle Uhrzeit nehmen, die Sekunden bis zur nächsten vollen 5 Minuten nehmen und Sleep damit bestücken, danach kannst du alle 5 Minuten deine Aktion ausführen. Wenn es exakt sein soll würde ich allerdings immer nach jeder ausgeführten Aktion die Sekunden neu berechnen, denn sonst passiert es, dass du irgendwann nicht mehr exakt um 20:55 sondern um einige Sekunden vorher/nachher dran bist.

    Falls aber der State irrelevant ist, würde ich einen ganz anderen Weg einschlagen! Lass doch dein System automatisiert die Aktion durchführen. Unter Linux wäre die Lösung über einen cronjob. Dafür bracuhst du einen Cron-Daemon (dcron, fcron, vixie-cron, usw.) Für Windows hab ich jetzt auf die Schnelle Z-Cron gefunden. Schaus dir an ob dir das was bringt...



  • @l'abra d'or, danke, dass du dich meinem Problem annimmst. Es soll immer exakt alle 5 Minuten die Aktion durchgeführt werden. Jedoch soll es im Programm integriert sein. Folgendes ist mir eingefallen:

    struct tm minutes;
    	while(true){
    		if(minutes.tm_min % 5 == 0){
    			std::cout << "5 Minuten vergangen" << std::endl;
    		}
    	}
    

    Dies belastet meine CPU zu 50% und ist inakzeptabel. Wenn ich Sleep(1000) ans Ende der if-Schleife setze, ist das ganze zu ungenau.



  • Sleep(100) ? Sleep(10) ? Sleep(5) ? Sleep(1) ?



  • while(true){ 
            if(minutes.tm_min % 5 == 0){ 
                std::cout << "5 Minuten vergangen" << std::endl; 
            Sleep(1);
            }
    

    Schon liegt die CPU auslastung bei 0%



  • Selbstverständlich sollte man noch die Time-Struct innerhalb der Schleife updaten.



  • Ok, Sleep(1) geht. Problem ist nur, dass "minutes" nicht aktualisiert wird.
    Hat wer 'ne Idee, wie ich minutes aktualisieren kann?





  • Kann mir nicht schnell jemand sagen, wie ich minutes aktualisieren kann?



  • Pferdi schrieb:

    Kann mir nicht schnell jemand sagen, wie ich minutes aktualisieren kann?

    Sorry für die Ausdrucksweise aber...bist du doof oder nur unglaublich faul?

    Hättest du auch nur einen Blick auf meinen Link geworfen, wäre es innerhalb von Sekunden klar gewesen.

    time_t rawtime;
    struct tm * timeinfo;
    
    time ( &rawtime );
    timeinfo = localtime ( &rawtime );
    


  • Icematix schrieb:

    Pferdi schrieb:

    Kann mir nicht schnell jemand sagen, wie ich minutes aktualisieren kann?

    Sorry für die Ausdrucksweise aber...bist du doof oder nur unglaublich faul?

    Hättest du auch nur einen Blick auf meinen Link geworfen, wäre es innerhalb von Sekunden klar gewesen.

    time_t rawtime;
    struct tm * timeinfo;
    
    time ( &rawtime );
    timeinfo = localtime ( &rawtime );
    

    Doch schon, so ähnlich hab ich's ausprobiert, nur meckert mein Compiler, wenn ich minutes als Zeiger verwende.

    time_t actual;
    	struct tm *minutes;
    	time(&actual);
    
    	while(true){
    		if(minutes.tm_min % 5 == 0){
    			cout << "5 Minuten vergangen" << std::endl;
    			time(&minutes);
    			minutes = localtime(&actual);
    		}
    		Sleep(1000);
    	}
    

    Der Microsoft-Compiler sagt:

    Links von ".tm_min" muss sich eine Klasse/Struktur/Union befinden. [if-Zeile]
    Typ ist 'tm *'
    Wollten Sie stattdessen '->' verwenden?
    
    'time': Konvertierung des Parameters 1 von 'tm **' in 'time_t *' nicht möglich [time(&minutes);]
    Die Typen, auf die verwiesen wird, sind nicht verknüpft; die Konvertierung erfordert einen reinterpret_cast-Operator oder eine Typumwandlung im C- oder Funktionsformat.
    


  • Sleep(1) ist auch eine Methode, die context switches künstlich in die Höhe zu treiben 😃

    Bevor du das jetzt ernsthaft so machst:

    for(;;)
    {
      DoAction();
    
      time_t rawtime;
      struct tm* timeinfo;
      time(&rawtime);
      timeinfo=localtime(&rawtime);
      Sleep((timeinfo->tm_min/5*5+5-timeinfo->tm_min)*60-timeinfo->tm_sec+1)*1000);
    }
    


  • Edit: time(&minutes); soll natürlich time(&actual); heißen, das hat sich schonmal erledigt.



  • Nuja, hab alle Fehler gefunden...

    time_t actual;
    	struct tm *minutes;
    	time(&actual);
    	minutes = localtime(&actual);
    
    	while(true){
    		if(minutes->tm_min % 5 == 0){
    			cout << "5 Minuten vergangen" << std::endl;
    			Sleep(58000);
    		}
    		time(&actual);
    		minutes = localtime(&actual);
    		Sleep(2000);
    	}
    


  • und woher kommt die magic number Sleep(58000);?



  • Und dir ist schon klar, dass deine Aktion alle zwei Sekunden ausgeführt wird, wenn du nicht gerade in einer Fünferminute bist?

    Edit: auch noch mal aufgedröselt:

    Sleep((
    //aktuelle Minute auf Fünfer abrunden
    timeinfo->tm_min/5*5
    //eine Fünferminute weiter als ob wir aufgerundet hätten
    +5
    //wir wollen nur die relative Zeit, also aktuelle Minuten wieder abziehen
    -timeinfo->tm_min)
    //das warn Minuten, also jetzt Sekunden
    *60-
    //verstrichene Sekunden der aktuellen Minute sind ja schon vergangen, können wir also beim Warten weglassen
    timeinfo->tm_sec
    //jeweils zur 01-Sekunde ausführen, um eventuellen Ungenauigkeiten aus dem Weg zu gehen (Sleep setzt dich z.B. bei 49:59 ab oder so)
    +1
    //jetzt Millisekunden
    )*1000);
    


  • Pferdi schrieb:

    Nuja, hab alle Fehler gefunden...

    time_t actual;
    	struct tm *minutes;
    	time(&actual);
    	minutes = localtime(&actual);
    
    	while(true){
    		if(minutes->tm_min % 5 == 0){
    			cout << "5 Minuten vergangen" << std::endl;
    			Sleep(58000);
    		}
    		time(&actual);
    		minutes = localtime(&actual);
    		Sleep(2000);
    	}
    

    Ich fürchte, ich muss mich Icematix anschliessen und feststellen, dass Du irgendwie zu bequem bist, wirklich darüber nachzudenken. Warum wartest Du irgendeine Zeit ab und schaust dann, ob es so weit ist, statt einfach auszurechnen, wie viel Zeit noch zu warten ist? Mit time bekommst Du die aktuelle Uhrzeit und du weisst, wann Du Deine Aktion das nächste mal ausführen willst. Aus der Differenz ergibt sich die Zeit, wie lange Du noch warten musst. Ausprogrammieren werde ich Dir das aber nicht.



  • Die Sleep(58000) habe ich eingebaut, da der if-Zweig sonst solange ausgeführt wird, bis die Teilung durch minutes->tm_min nicht mehr möglich ist. Die Division ist in einer Minute sehr oft möglich, begrenzent ist die Sleep()-Funktion.



  • Wie waere es mit 'nem Cron-Job?



  • Entschuldigt meine gestrige Ungehobeltheit. Nun habe ich meinen Code nach euren Vorschlägen zurechtgebastelt (oder -kopiert).

    time_t rawtime;
    	struct tm* timeinfo;
    	time(&rawtime);
    
    	while(true){
    		time(&rawtime);
    		timeinfo=localtime(&rawtime);
    		Sleep(((timeinfo->tm_min/5*5+5-timeinfo->tm_min)*60-timeinfo->tm_sec+1)*1000);
    		cout << "5 Minuten vergangen" << endl;
    	}
    

Anmelden zum Antworten