LabVIEWForum.de - Queued State Machine Zeitverzögerung

LabVIEWForum.de

Normale Version: Queued State Machine Zeitverzögerung
Du siehst gerade eine vereinfachte Darstellung unserer Inhalte. Normale Ansicht mit richtiger Formatierung.
Hallo zusammen,

da ich erst seit kurzem mit Queued State Machine arbeite (hierbei habe ich viel von dem QSM PC EXAMPLE gelernt und abgekupfert) und das ganze erst noch zu verstehen probiere wollte ich wegen einer Ungereimtheit zu dem Datenaustausch zwischen VI´s nachfragen.

Ich habe ein Main VI (VOC_Cuvette_5_00.vi) und mehrere sub VI´s wobei für mein Problem eigentlich nur das VOC_Arduino_5_00.vi benötigt wird.
Zur Erklährung das VOC_Arduino VI händelt die Kommunikation zu meinem Mikrocontroller list jede Sekunde Daten aus und sendet diese Daten u.a. zu dem Main Vi um Graphisch dargestellt zu werden.
Nun ist es so, dass die Daten auch ankommen, jedoch Zeitverzögert und die Verzögerung erweitert sich immer mehr und mehr, je länger das Programm läuft, sodass es schon nach wenigen Minuten soweit ist, sobald keine Daten mehr gelesen werden das Main Vi immer noch Daten empfängt (welche empfangen wurden, jedoch in einer Warteschleife hängen). Dies Verzögerung ist auch von der Wait[ms] funktion abhängig, denn je länger gewartet wird umso größer die Verzögerung, und das obwohl alle Programmteile zu 90% im IDLE Modus warten.
Wenn ich jedoch die 100ms Verzögerung aus meinem Main VI rausnehme (zulasten der CPU, diese geht von 1% auf 25% Auslastung) passiert das nicht, auch wenn ich über Nacht das Programm durchlaufen lasse.Bahn

Ich hoffe, dass mir jemand weiterhelfen kann denn ich habe keine Ahnung wo ich jetzt noch anfangen soll.

Gruß

Simon
lv13_img
Du fügst einfach viel zu oft das Kommando "Idle" zu deiner Main-Queue hinzu, wie einfaches Debugging zeigt:
[attachment=53267]
Dadurch wird deine Queue immer länger, frisst Speicher, alles wird langsamer (übrigens auch beim Entfernen deines Waits).

Meine Empfehlung:
Verzichte auf das explizite Hinzufügen des Kommandos "Idle" (im Screenshot nur zu sehen im IDLE Case, aber ich habe es in allen Cases entfernt), werte stattdessen den Time-Out-Ausgang der Dequeue Funktion aus und springe nur in diesem Fall in den Idle Case:
[attachment=53268]
Dasselbe solltest du dann in deinen Prozess VIs ebenso machen.

Gruß, Jens

EDIT & P.S.: Ansonsten Respekt für den sauberen Source-Code, sieht man leider viel zu selten hier.
Ist ja klar, im Idle-State hast Du die Wartezeit drin, und von fast jedem Status aus, auch aus dem Idle-Status selbst, fütterst du immer die Queue, um den Idle-D status erneut auszuführen. Das hat zur Folge, dass in der while-Schleife nur höchstens all 100ms etwas "Vernüftiges" aus der Queue abgearbeitet werden kann - und das ist zu wenig, die Queue wird im Lauf der Zeit immer voller.
Wozu überhaup der Idle-Status? Die Funktion "Element aus Queue entfernen" wartet doch, wenn nichts mehr in der Queue ist, und das ist dann gewissermaßen der Idle-Zustand. Du kannst den Idle-Status von mir aus auch lassen, aber dann nicht von da aus erneut immer wieder die Queue mit "Idle" füttern - und natürlich ohne Wartezeit.
Die Waits in der oberen Schleife sind auch überflüssig: Weg mit dem 10ms Wait, und weg mit dem ganzen Timeout-Case.

Edit: Die Doppelbelastung, von Jens und von mir annähernd dasselbe lesen zu müssen, macht Dir doch hoffentlich nichts aus? Big Grin
Erstmal vielen Dank für eure schnellen Rückmeldungen.

@Jens
Ich habe deinen Vorschlag umgesetzt und es funktioniert einwandfrei. Vielen Dank. Und auch danke für dein Kompliment, es ist immer eine Freude, wenn man eine saubere Arbeit abliefern kann. (Dieses Forum hat auch wesentlich dazu beigetragen.)

@Luki
Der IDLE Status wird eigentlich nur in manchen Prozess VI´s benötigt, deshalb habe ich ihn, falls vielleicht doch gebraucht, noch in allen VI´s gelassen.
Ja die 10ms Waits in der oberen schleife sind wirklich überflüssig, habe sie auch schon entfernt.
Den Timout Case kann ich nicht entfernen, da ich den Timout brauche um das Programm ordentlich zu schließen. Denn nur so wird alle 100 ms (können auch mehr sein) die gesamte Case Strukture verlassen und meine Globale Variable abgefragt. Sonst würde das gesamte Programm nur beendet werden sobald in jedem Fenster ein Knöpfchen gedrückt wird. Diese Erkenntnis hatte auch lange auf sich warten lassen. Gäbe es dazu auch eine andere Möglichkeit?

Auf alle Fälle Vielen Dank euch beiden.
(03.06.2015 08:33 )NISI schrieb: [ -> ].. das gesamte Programm nur beendet werden sobald in jedem Fenster ein Knöpfchen gedrückt wird. Diese Erkenntnis hatte auch lange auf sich warten lassen. Gäbe es dazu auch eine andere Möglichkeit?
Es gibt ein sehr elegante Lösung, die aber etwas umständlich daherkommt - was Dich nicht abhalten sollte das so zu machen.
Schau Dir dazu mal das Beispielprojekt "Handler für Nachrichten Queues" an.
Die Schrittfolge beim Programmabbruch ist dort genau so wie bei Dir, nur der letzte Schritt wird anders ausgeführt:
Die Ereignisschleife (oben) wird nicht über die Abfrage einer lokalen Variablen beendet, sondern es wird von der unteren Schleife ein benutzerdefiniertes Ereignis ausgelöst.
Ja diese Lösung ist wesentlich eleganter.

Danke für den Tipp.
Referenz-URLs