Re: Wait wartet nicht Kategorie: Programmierung (von JackFRost - 5.12.2007 22:05) | |
Als Antwort auf Re: Wait wartet nicht von JackFrost - 5.12.2007 22:04
| |
> > Hallo Mark, > > > > Ich vermute, da� Du einen Fehler in Deinem Programm hast, welcher beim > > geposteten Code nicht enhalten ist. > > > > Denn wait funktioniert eindeutig. > > Sogar die beiden Threads funktionieren. > > Gewöhne Dir aber bitte eine andere Klammersetzung an. > > Ich wei�, da� es in C üblich ist, die geschweiften Klammern noch in der Zeile > > des "einleitenden" Befehls zu setzen und gern auf richtiges Einrücken zu verzichten. > > Aber spätestens, wenn man einen Fehler suchen mu�, behindert das einen sehr. > > Daher rücke lieber so ein: > > > > long timer; > > int x,y; > > > > thread regeln > > { > > loop > > { > > timer=system.timer(); > > y=y+1; > > wait timer+10000<=system.timer(); > > } > > } > > > > thread main > > { > > run regeln; > > x=x+1; > > } > > > > Bei kurzen Routinen fällt es zwar noch nicht stark auf, aber bei längeren > > kann es aber sonst schnell unübersichtlich werden. > > > > Nun aber zum wait zurück: > > Prinzipiell kann man hier wait verwenden. Jedoch ist ein sleep eindeutig weniger belastend! > > Ich wei� nicht, wie Du auf die Idee kommst, ein sleep würde andere Threads > > in Mitleidenschaft ziehen? > > Ein sleep ist eine einzge VM-Instruktion. Dazu noch ein Parameter der einmal > > auf den Stack geschoben wird. > > Um die Funktionsweise des sleep einmal zu erläutern: > > Gelngt der Programmablauf zu einem sleep, so wird zuerst der Wert(Konstante oder > > Inhalt einer Variable) auf den Stack geschoben, und dann VM_SLEEP ausgeführt. > > VM_SLEEP ist zweigeteilt. Es wird daher geprüft, ob sich der Thread bereits in > > einer "Sleep-Phase" befindet. > > > > Ist das nicht der Fall, werden ein Active-Flag undzwei interne Threadvariablen mit > > dem Startzeitpunkt(Timer) des Sleeps, sowie des Endzeitpunkts beschrieben. > > Anschlie�end wird der Threadpointer um 1 verringert, damit sich VM_SLEEP erneut durchlaufen > > wird, sobald der Thread wieder "Rechenzeit" bekommt. > > Jetzt wird noch die Rechenzeit abgegeben. > > > > Erhält nun der Thread wieder Rechenzeit, so wird das Active-Flag des Sleeps abgefragt. > > Da dieses nun auf True steht, erfolgt nun eine weitere Abfrage, die prüft, ob bereits > > die Wartezeit abgelaufen ist. > > Ist diese nicht abgelaufen, wird der Threadpointer wieder um eins verringert und > > die Rechenzeit abgegeben. > > Ist die Wartezeit abgelaufen, wird das Flag gelöscht, und der Thread wird > > nach dem sleep fortgesetzt. > > > > Im Ganzen nimmt VM_SLEEP bei jedem Durchlauf nur eine VM-Instruktion in Anspruch. > > > > Wenn statt dem sleep nun eine Konstruktion mit wait gemacht wird, > > belastet dies die CC2 mehr. Es steht dann weniger "Rechnzeit für andere Threads zur Verfügung. > > Denn ein wait besteht mehr als aus einer VM_Instruktion. > > Genaugenommen entspricht das etwa dieser Schleife: > > loop > > { > > if <Bedingung> break; > > yield; > > } > > Eine einfache Schleife besteht aus einer VM_Instruktion. > > Dazu kommt noch das if und der Sprung und aus der Schleife: zwei Instruktionen > > Und das yield mit einer Instruktion. > > Die Bedingung selbst besteht natürlich auch aus einer Anzahl an Instruktionen. > > Das timer+10000<=system.timer() in Deinem Fall sind 5 Instruktionen. > > Somit ergibt sich bei Deinem wait eine Anzahl von 9 Instruktionen. > > Von diesen 9 Instruktionen werden, solange die Bedingung nicht erfüllt ist, immer 8 durchlaufen. > > Ist die Bedingung erfüllt, sind es ab Schleifenbeginn "nurnoch" 7 Instruktionen. > > (Die IDE erzeugt aus wait eine kleine Schleife, da wait keine eigene VM_Instruktion ist.) > > > > Dagegen stehen die bei sleep anfänglich zwei Instruktionen, und während > > des "Wartens" eine Instruktion. > > Somit ist ein sleep immer ressourcenschonender als ein vergleichbares Konstrukt mir wait. > > > > �brigens sollte man, um mit dem Timer eine Wartezeit zu berechnen, auf dieses Konstrukt verzichten: > > timer+10000<=system.timer() > > Es hat den Nachteil, da� bei einem �berlauf der Vergleich durch die negativen Werte > > eine Zeit lang ein gegenteiliges Ergebnis liefert. (Hier: gut 10s lang) > > Besser ist es, dies so zu berechnen: > > system.timer()-timer<=10000 > > Hier wird die Differenz gebildet. Zu beachten ist aber, da� immer vom "höheren" Wert > > der "kleinere" abgezogen wird.(Oder anders ausgedrückt: Vom aktuelleren (Timer-)Wert mu� > > immer der alte Wert abgezogen werden.) > > Nur so ist die Differenz immer positiv. > > Au�er natürlich, wenn über dreieinhalb Wochen vergehen. Denn solange dauert es, > > bis der Timer seine über 2,1Mrd. erreicht, wo er schlie�lich überläuft. > > Aber Zeitdifferenzen von mehreren Wochen erfasst man sicher nicht mit dem ms-Timer. ;-) > > Probleme mit einer falschen Berechnung treten daher erst nach ca. 3,5 Wochen auf, > > und wiederholen sich dann etwa alle 7 Wochen. (solange dauert es, bis der Timer einmal rum ist.) > > > > Daher nochmal zur Wiederholung: > > Man rechnet immer "Zeit_neu Minus Zeit_alt = Differenz". > > > > Aber um nochmal zu Deinem direkten Problem zu kommen: > > Ich vermute, da� in Deinem restlichen Programm irgendwo Fehler sind. > > In diesem Fall würde ich sagen, da� Du irgendwo au�erhalb definierter > > Arraygrenzen auf Variablen zugreifst, und somit auch Deine timer-Variable erwischt. > > Nimm einmal Deine Schleife, wie sie ist, ersetze das wait dennoch durch ein sleep, > > und überwache aus einem anderen Thread die timer-Variable. > > Wenn diese sich öfters als alle etwa 10sek. (sleep 10000;) ändert, > > dann ist mein Verdacht bestätigt. Dann hei�t es das Programm nach solchen > > �berschreitungen zu durchsuchen. > > Das naheliegenste sind Variabeln, die unmitelbar vor long timer; definiert sind. > > Führe daher bitte mal alle globalen Variablen des Moduls in der korrekten Reihenfolge auf. > > Wenn in diesem Modul keine weiteren globalen Variablen definiert sind, > > dann die des vorherigen Moduls. > > > > MfG André H. > > > > > > > Hallo! > > > Ich verzweifle grade an simpelsten Abläufen! Folgenden Code habe ich: > > > > > > long timer; > > > > > > thread regeln > > > { > > > loop{ > > > timer=system.timer(); > > > do something....; > > > > > > wait timer+10000<=system.timer(); > > > } > > > } > > > > > > main { > > > run regeln; > > > do something else...; > > > } > > > > > > Aus dem Main-Thread soll also einfach nur der Thread "Regeln" aufgerufen werden, in dem > > > dann eine Schleife abläuft und alle 10 Sekunden etwas tun soll. Das Problem dabei ist, dass sie > > > nicht 10 Sekunden wartet, sondern direkt weiter macht. Ich habe auch schon ausprobiert, das Ganze > > > ohne die Schleife zu machen, aber auch das funktionierte nicht. Wenn ich allerdings ein einfaches sleep > > > 1000 reinsetze, pausiert er, zieht aber die anderen Threads leistungstechnisch nach unten. > > > Hat jemand eine Idee, woran es liegen könnte oder wie ich das Problem elegant umgehen könnte? > > > Viele Grü�e, > > > Mark > > > > > > > > Hiermit könnte es gehen. > > > long solldrehzahl,timer; > byte versuche,minimaledrehzahl; > thread Motorstarten > { > wait global.startmotor; > global.startmotor = 0; > global.startok = 0; > ports.set(1,1); // Port an dem der Starter des Motors hängt > versuch = 1; > timer = system.timer(); > sleep 100; > loop > { > if ports.getfreq(2) >= solldrehzahl // Port an dem der Drehzahlmesser hängt > { > global.startok = 1; > > break; > } > if system.timer()-timer>=5000 > { > if ports.getfreq(2) >= solldrehzahl // Port an dem der Drehzahlmesser hängt > { > global.startok = 1; > break; > } > else > { > if versuche >= 3 > { > global.startok = 2; > break; > } > sleep 10000; > ports.set(1,1); // Port an dem der Starter des Motors hängt > versuch = versuch + 1; > timer = system.timer(); > } > } > > } > > > } > > > > thread main > { > run Motorenstart; > } > > > Es muss aber die Solldrehzahl definiert werden. Ich habe mal angenommen das sie als Frequenz anliegt. > Man braucht auch ein Modul Global wo die Variablen startmotor und startkok enthalten sind. > Wenn die Variable global,startmotor ungleich 0 wird dann wird der motor gestartet. > Die Fehlermeldung wird über global.startok übertragen. Wenn das Ergebnis 1 ist dann ist alles ok, > bei 2 ist der Motor nach 3 Versuchen nicht angelaufen. > Als Pause zwischen den Anläufen wurden 10 sec gewählt. > > Gruss JackFrost Ups falscher Thread :( Bitte löschen wenn es geht. Gruss JackFrost | |
Antwort schreiben Antworten: |