Zur Übersicht - INFO - Neueste 50 Beiträge - Neuer Beitrag - Suchen - FAQ - Zum CC1-Forum - Zum CC-Pro-Forum

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: