Re: Wait wartet nicht Kategorie: Programmierung (von JackFrost - 5.12.2007 22:04) | |
Als Antwort auf Re: Wait wartet nicht von André H. - 31.05.2007 11:21
| |
> 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 | |
Antwort schreiben Antworten: Re: Wait wartet nicht (von JackFRost - 5.12.2007 22:05) |