LabVIEWForum.de - Design "Erzeuger/Verbraucher

LabVIEWForum.de

Normale Version: Design "Erzeuger/Verbraucher
Du siehst gerade eine vereinfachte Darstellung unserer Inhalte. Normale Ansicht mit richtiger Formatierung.
Seiten: 1 2
Hallo,
ich habe noch eine Frage zum Design "Erzeuger/Verbraucher:

Ich verwende Erzeuger-Verbraucher um das Erzeugen der Ereignisse von der Verarbeitung zu trennen.
So wie ich das sehe, werden die Ereignisse ja in eine Queue gestellt, aus der sich dann die Verbraucherschleife bedient.

Also Beispiel: ein Button "Hallo" wird gedrückt, die Erzeugerschleife stellt den String Hallo in die Queue.

Dort holt die Verbraucherschleife den String Hallo raus, und verarbeitet den.

Ich stelle nun fest, dass wenn diese Verarbeitung z.B. 10 sekunden dauert, das ganze GUI 10 Sekunden blockiert ist.

Ich verstehe nicht, wieso der Button „Hallo“ (andere Buttons genauso…) gedrückt bleibt, bis der Code der Verbraucher-Case durch ist.

Ich hätte eigentlich gedacht, der Button macht einen event, der wird in der Erzeuger-Schleife in die Queue eingereiht, und fertig ist. Aber der Button bleibt unten, bis die betreffende Verbraucher-Queue abgearbeitet ist. Also nicht asynchron, nicht parallel.

Die GUI bleibt blockiert. Das gefällt mir nicht…Dry

Kann man das so abändern, dass die GUI immer funktioniert, und die Erzeugerschleife und die Verbraucherschleife parallel ausgeführt werden ?

Noch lieber hätte ich, wenn praktisch jeder case meiner Verbraucherschleife parallel läuft, quasi in einem eigenen Thread, Tongue aber ich will ja nicht zu extrem werden.

Ich verwende LV8.6, XP und habe 4 Cores.

Werner
' schrieb:Also Beispiel: ein Button "Hallo" wird gedrückt, die Erzeugerschleife stellt den String Hallo in die Queue.
Dort holt die Verbraucherschleife den String Hallo raus, und verarbeitet den.
So geht das.

Zitat:Ich stelle nun fest, dass wenn diese Verarbeitung z.B. 10 sekunden dauert, das ganze GUI 10 Sekunden blockiert ist.
Dann hast du was falsch programmiert.

Zitat:Kann man das so abändern, dass die GUI immer funktioniert, und die Erzeugerschleife und die Verbraucherschleife parallel ausgeführt werden ?
Klar, du must dein Programm nur richtig machen. Wink


Zeig mal ein (Muster-)VI, das den Fehler zeigt.
' schrieb:Hallo,
ich habe noch eine Frage zum Design "Erzeuger/Verbraucher:

Ich verwende Erzeuger-Verbraucher um das Erzeugen der Ereignisse von der Verarbeitung zu trennen.
So wie ich das sehe, werden die Ereignisse ja in eine Queue gestellt, aus der sich dann die Verbraucherschleife bedient.

Also Beispiel: ein Button "Hallo" wird gedrückt, die Erzeugerschleife stellt den String Hallo in die Queue.

Dort holt die Verbraucherschleife den String Hallo raus, und verarbeitet den.
Korrekt. So sollte es sein.

' schrieb:Ich stelle nun fest, dass wenn diese Verarbeitung z.B. 10 sekunden dauert, das ganze GUI 10 Sekunden blockiert ist.

Ich verstehe nicht, wieso der Button „Hallo“ (andere Buttons genauso…) gedrückt bleibt, bis der Code der Verbraucher-Case durch ist.

Ich hätte eigentlich gedacht, der Button macht einen event, der wird in der Erzeuger-Schleife in die Queue eingereiht, und fertig ist. Aber der Button bleibt unten, bis die betreffende Verbraucher-Queue abgearbeitet ist. Also nicht asynchron, nicht parallel.

Die GUI bleibt blockiert. Das gefällt mir nicht…Dry
Das kann ich mir vorstellen. Wie IchSelbst bereits gesagt hat, hast du wohl etwas falsch gemacht.

' schrieb:Kann man das so abändern, dass die GUI immer funktioniert, und die Erzeugerschleife und die Verbraucherschleife parallel ausgeführt werden ?
Ja.

' schrieb:Noch lieber hätte ich, wenn praktisch jeder case meiner Verbraucherschleife parallel läuft, quasi in einem eigenen Thread, Tongue aber ich will ja nicht zu extrem werden.
Wie soll denn jeder Case parallel abgearbeitet werden? Du kannst mehrere parallele Schleifen ausführen. Standartmäßig habe ich mindestens drei Schleifen. Eine Producer, eine Consumer und eine die mein Frontpanel updated. Letztere ist wiederum von der Consumer-Schleife abhängig. Mit dieser Architektur kannst du meiner Meinung nach 80-90% deiner Aufgabenstellungen erledigen. Du kannst allerings auch noch mehr parallele Schleifen hinzufügen. Da sind dir deiner Fantasie keine Grenzen gesetzt.
' schrieb:Ich stelle nun fest, dass wenn diese Verarbeitung z.B. 10 sekunden dauert, das ganze GUI 10 Sekunden blockiert ist.
Die Oberfläche wäre z.B. dann für die Dauer des Eventcases blockiert, wenn im Eventcase "Frontpanale sperren" angekäckelt ist. Oder wenn das Resetten des Tasters an der falschen Stelle gemacht wird.
Hi danke für die guten Anregungen.
Ich arbeite noch damit, dauert noch was, da ichs noch nicht ganz verstanden habe.

Ausserdem versteh ich nicht, wie das hier mit dem zitieren geht... sorry...

Zitat: Die Oberfläche wäre z.B. dann für die Dauer des Eventcases blockiert, wenn im Eventcase "Frontpanale sperren" angekäckelt ist. Oder wenn das Resetten des Tasters an der falschen Stelle gemacht wird.

Also:
Ich vermute, du hast recht.
Ich verwende den OK-Button so wie du vermutest.

Bei Ereignisse bearbeiten steht auch extra:
Hinweis: Bei der Verarbeitung einer Wertänderung (genau das hab ich gewählt) an einem gelatschten boolschen Element wird nicht automatisch der vorgesehene Schaltvorgang ausgeführt. Um das Element ordnungsgemäß in den Ausgangszustand zurückzusetzen, muss das Element erst ausgelesen werden.

Nur: ich lese den Button doch oben in der Erzeugerschleife aus, zumindest hab ich das Ding da reingezogen. Ich versteh nicht, wieso das Mistding gedrückt bleibt, auch wenn der text in die Queue gestellt wurde.
In meiner Verbraucherschleife ist der Button gar nicht drinn, trotzdem kommt der hoch, wenn die Verbraucherschleife diesen Case abgearbeitet hat. Wie funktioniert das ? Ich verstehs nicht.

Oben im Ereignis-Case habe ich die Checkbox

[x]Frontpanel sperren, bis der Code für dieses Ereignis abgearbeitet wurde

Extra deaktiviert, trotzdem kann ich an der GUI nix bedienen bis der Case fertig ist.
Komisch.

Zitat: Wie soll denn jeder Case parallel abgearbeitet werden? Du kannst mehrere parallele Schleifen ausführen. Standartmäßig habe ich mindestens drei Schleifen. Eine Producer, eine Consumer und eine die mein Frontpanel updated. Letztere ist wiederum von der Consumer-Schleife abhängig. Mit dieser Architektur kannst du meiner Meinung nach 80-90% deiner Aufgabenstellungen erledigen. Du kannst allerings auch noch mehr parallele Schleifen hinzufügen. Da sind dir deiner Fantasie keine Grenzen gesetzt.

Danke für die Anregung. Also deine Producer, deine Consumer und deine Frontpanelschleife arbeitet dann wirklich parallel ? Die Queue zwischen Consumer und Producer hindert nicht die parallele Ausführung ?

Deine Frontpanelschleife ist eine einfache While mit Timer drinn, die etwa sekündlich oder so abläuft ?

Ich möchte das VI so bedienen, wie ein Messgerät. Im Hintergrund läuft die Messung, Anzeigen werden aktualisiert und ich kann die GUI bedienen. Genau das scheint ja mit deinem Konzept zu gehen. Richtig ?

Werner
' schrieb:Also:
Ich vermute, du hast recht.
Ich verwende den OK-Button so wie du vermutest.

Bei Ereignisse bearbeiten steht auch extra:
Hinweis: Bei der Verarbeitung einer Wertänderung (genau das hab ich gewählt) an einem gelatschten boolschen Element wird nicht automatisch der vorgesehene Schaltvorgang ausgeführt. Um das Element ordnungsgemäß in den Ausgangszustand zurückzusetzen, muss das Element erst ausgelesen werden.
Eine Latch-Button platziere ich IMMER in den Value-Change-Case der Event-Struktur des Buttons! Damit wird er in diesem Case ausgelesen und zurückgesetzt.

Offtopic2
Zum Thema zitieren:
Erst den Zitieren Button unterhalb des Beitrages bzw. der Beiträge (ja, geht auch für mehrere), den/die du zitieren willst, anklicken,
[attachment=21582]
dann Antwort schreiben.

Oder nachträglich in "quote" Tags setzen - Text markieren, dann Button drücken:
[attachment=21583]

Gruß, Jens
' schrieb:Nur: ich lese den Button doch oben in der Erzeugerschleife aus, zumindest hab ich das Ding da reingezogen. Ich versteh nicht, wieso das Mistding gedrückt bleibt, auch wenn der text in die Queue gestellt wurde.
Oh, da gibt es schon noch Möglichkeiten. Das Auslesen des Elementes, in dessen Folge zuerst mal lediglich der Wert des Elementes zurückgesetzt wird, erzwingt zwar einen Refresh am Bildschirm - der kann aber zeitversetzt (zwischen 1ms und 10 Sekunden sag ich jetzt mal) passieren.

Wenn die gesamte GUI (also dein FP) blockiert ist, kann das auch daran liegen, dass irgendwo eine While-Schleife (z.B. die vom Verbraucher) soviel Prozessor-Leistung für das Blockdiagramm verbraucht, dass keine Zeit mehr für den FP-Refreh bleibt. Manchmal hilf da eine Wartezeit von 1ms in die While-Schleife zu plazieren.

Gut wäre es, wenn du ein MusterVI mit den Auffälligkeiten erstellen kannst.
' schrieb:Offtopic2
Zum Thema zitieren:
Erst den Zitieren Button unterhalb des Beitrages bzw. der Beiträge (ja, geht auch für mehrere), den/die du zitieren willst, anklicken,
[attachment=49706:Image01.png]
dann Antwort schreiben.

Oder nachträglich in "quote" Tags setzen - Text markieren, dann Button drücken:
[attachment=49707:Image02.png]

Gruß, Jens

Jens,
danke für die Hilfe beim zitieren... ist ja praktisch... wenn mans erst mal verstanden hatHmm

Werner
' schrieb:Oh, da gibt es schon noch Möglichkeiten. Das Auslesen des Elementes, in dessen Folge zuerst mal lediglich der Wert des Elementes zurückgesetzt wird, erzwingt zwar einen Refresh am Bildschirm - der kann aber zeitversetzt (zwischen 1ms und 10 Sekunden sag ich jetzt mal) passieren.

Wenn die gesamte GUI (also dein FP) blockiert ist, kann das auch daran liegen, dass irgendwo eine While-Schleife (z.B. die vom Verbraucher) soviel Prozessor-Leistung für das Blockdiagramm verbraucht, dass keine Zeit mehr für den FP-Refreh bleibt. Manchmal hilf da eine Wartezeit von 1ms in die While-Schleife zu plazieren.

Gut wäre es, wenn du ein MusterVI mit den Auffälligkeiten erstellen kannst.

Hi,
ich antworte so spät, weil ich langsam begreife wo es hängt.
Meine Erzeugerschleife reagiert auf Drücken von Buttons meines Frontpanels, und stellt dann passende Strings in die Queue.
Meine Verbraucherschleife holt sich diese Strings raus, und bearbeitet sie im passenden case.
Auch wenn ich in so einem Case einen LabVIEW-Timer mit einer Wartezeit von 10000ms stelle, funktioniert die GUI korrekt.

Ich habe aber eine DLL in C (VS2005) erstellt, die ich im betreffenden case aufrufe. Diese DLL kommuniziert über TCP/IP mit einem SerialDeviceServer, der im Prinzip eine RS232 Schnittstelle bereitstellt. Daran hängen RS232-Geräte (mehrere). Die Kommunikation funktioniert so, dass so ein Gerät ein Kommando gesendet bekommt (z.B.: "VALVE7 OPEN") und dann antwortet (z.B: "OK"). Diese Antwort erfolgt zeitverzögert, z.B.: nach 10 Sekunden.

Was bei mir vermutlich der Fall ist, ist dass LV in meine DLL springt (CallLibraryFunctionNode) und da halt etwa 10 Sekunden hängt. Im C-Code hänge ich in den 10 Sekunden in einer while-Schleife, wo ich mit sleep(100); halt warte, und dachte so CPU-Zeit abzugeben. Aber offensichtlich blockiere ich so das gesamte LabVIEW, so dass weder meine GUI-Buttons sich bewegen, noch sonst was ausgeführt wird.

Hier ein C-Code-Fragment von mir:

[code]//unterscheiden zwischen UDP und TCP
' schrieb:Diese DLL kommuniziert über TCP/IP mit einem SerialDeviceServer,
Über TCP/IP? Da, so befürchte ich, kann es zu einem Hängen des gesamten Prozesses kommen. Der gesamte Prozess wäre wie DLL und LV.

Zitat:wo ich mit sleep(100); halt warte, und dachte so CPU-Zeit abzugeben.
Die Sache mit CPU-Zeit abgeben stimmt schon so. Aber: Während dieser 100ms steht der gesamte Prozess, der sleep() aufruft - also die DLL und das LV-Programm !

Zitat:Hier ein C-Code-Fragment von mir:
muss ich mir noch ankucken.


Zitat:Ist das mein Fehler ?
Aus Erfahrung würde ich auf zwei Sachen tippen.
Sleep(): Sleep() stoppt den gesamten Prozess.
TCP/IP: Wenn der TCP/P-Socket nicht event-getriggert arbeitet, könnte es schon sein, dass die TCP/IP-Unterprogramme erst beendet werden, wenn daten ankommen, oder wenn ein Timeout eintritt.

Zitat:KannLv86_imgüberhaupt weiterlaufen, während ein VI in einer externen DLL steckt
Hier würde ich sagen: Das sollte gehen.
Das SubVI, welches die DLL aufruft, müsste in einer eigenen Task (= While-Schleife) laufen.

Zitat:und dort in einer Schleife mit sleep() verweilt ?
Probier's mal aus: SubVI mit DLL auf eigener While-Schleife. Möglicherweise managert LV diese parallele While-Schleife so, dass der Effekt, der mit mit Sleep() bekannt ist, eleminiert wird. Ein Versuch wäre es Wert.
Seiten: 1 2
Referenz-URLs