05.12.2010, 21:17
(Dieser Beitrag wurde zuletzt bearbeitet: 05.12.2010 22:11 von Matze.)
|
Matze
LVF-Team
Beiträge: 1.027
Registriert seit: Apr 2010
20xx
2010
DE_EN
7xxxx
Deutschland
|
Wie auf eine Instanz aus parallelen Prozessen zugreifen?
Wäre jemand von euch so nett, mir zu erklären, wie das funktioniert? So ganz steige ich da nicht durch.
Beim Erzeugen der Instanz wird eine Referenz einer 2 Instanz (komplett andere Klasse) in die Queue geschrieben
Möchte man auf die Referenz zugreifen können, wird eine Referenz aus der Queue gelesen (eine ist ja bereits drinnen) und mit dieser gearbeitet. Anschließend wird die Referenz wieder in die Queue eingetragen, um erneut darauf zugreifen zu können.
Das verhindert natürlich, dass parallel darauf zugegriffen wird, da die Queue zur Zeit der Bearbeitung leer ist - in diesem simplen Beispiel.
Wenn ich nun parallele Schleifen nutze, dann funktioniert das Ganze nicht unbedingt, da es sein kann, dass eine Schleife fortlaufend die Queue beschreibt und daraus liest und andere Schleifen nicht zum Zuge kommen oder?
Kann man das nicht direkt mit einer einzigen Klasse machen und dort die Referenzen nutzen?
Dann könnte ich alle Methoden der Klasse parallel verwenden. Die eine Klasse wird aktuell ja nur für die Queue-Funktionalität verwendet, wenn ich das richtig sehe.
|
|
|
06.12.2010, 11:20
|
IchSelbst
LVF-Guru
Beiträge: 3.700
Registriert seit: Feb 2005
11, 14, 15, 17, 18
-
DE
97437
Deutschland
|
Wie auf eine Instanz aus parallelen Prozessen zugreifen?
' schrieb:Beim Erzeugen der Instanz wird eine Referenz einer 2 Instanz (komplett andere Klasse) in die Queue geschrieben.
In die Queue wird die zu verwendende Instanz (blau) geschrieben. Die Referenz der Queue ist ein Datenteil einer zweiten Klasse (grün). Ob diese zweite Klasse notwendig ist, müsste man ausprobieren.
Ganz links (Create.vi) wird eine Instanz erzeugt: Blaue Linie. Die Instanz-Referenz wird in eine Queue geschrieben: Grüne Linie. In Set und Get wird nichts weiter gemacht, als die Referenz aus der Queue heraus gelesen und "benutzt". Hier endet das erste Beispiel (paradigm 1). Vorteil dieses Verfahrens ist es, dass von der blauen Klasse im "Arbeits-VI" nichts "zu sehen" ist. So, dass man nichts sieht, finde ich das gut. Hier ist die Klassen-Referenz pro VI-Aufruf gekapselt.
Der ganze rechte Teil macht nichts anderes, als zuerst die Referenz (aus der Queue) auszulesen, dann per dieser Referenz Daten zu bearbeiten. Zuletzt muss die Referenz natürlich wieder in die Queue. Dieses Verfahren finde ich nicht so schön. Hier ist die Klassen-Referenz in Teilen des VIs nicht mehr gekapselt. Daher darf zu diesen Zeiten der Datenfluß nicht unterbrochen werden.
Zitat:Wenn ich nun parallele Schleifen nutze, dann funktioniert das Ganze nicht unbedingt, da es sein kann, dass eine Schleife fortlaufend die Queue beschreibt und daraus liest und andere Schleifen nicht zum Zuge kommen oder?
Ja, hier sehe ich auch ein Problem. Das lässt sich aber minimieren, indem der eine Prozess nur in einem bestimmten Raster arbeitet. Zudem sollte die Queue so kurz wie möglich leer sein. [*nachdenk*] Hier sehe ich aber auch ein Problem.
Zitat:Kann man das nicht direkt mit einer einzigen Klasse machen und dort die Referenzen nutzen?
Ausprobieren.
Ich sag mal ganz unprofessionell: Referenz in Globale Variable legen. Dann ist die Referenz überall erhältlich - mit allen Risiken, die ja durch die Queue eliminiert werden.
Ich verwende meine MöchteGernKlassen wie folgt: Es gibt eine Queue, in die Steuerdaten geschrieben werden. Wenn also jemand die Daten der Klasse ändern will, schreibt er einen Datensatz in die Queue. Das "Klassen-Main-VI" pollt neben der eigentlichen Arbeit diese Queue. Steht da was drinnen, wird das entsprechende ausgeführt. Dieser Datensatz in der Queue entspricht einem Property. Zum Auslesen der Public-Daten gibt es einen Melder, der die Public-Daten enthält. Es ist mit allen Konsequenzen zu beachten, dass das Verwenden einen Queue zu einem asynchronen Ablauf führt! Man kann Propertys auch ohne Queue realisieren - das hat aber wegen der sehr beschränkten Anzahl von Eingängen eines VIs enge Grenzen.
Dieses Verfahren kann man natürlich auch mit einer Klassen-Instanz machen. Die Instanz-Referenz wäre dann im "Klassen-Main-VI" gekapselt und von außen nicht zugänglich - aber dafür gibt es sie nur ein einziges Mal.
[*grübel*]
Wenn du eine Referenz verwendest (siehe dein Beispielbild), werden vermutlich Probleme auftreten. Diese Referenz gilt als "global". Irgendwann musst du die Referenz dereferenzieren. D.h. aber: zwei Datenflüsse für eine Instanz! Das führt, wenn auch praktisch nur sehr schwer nachweisbar, zu RaceConditions.
Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
|
|
|
06.12.2010, 19:51
(Dieser Beitrag wurde zuletzt bearbeitet: 06.12.2010 19:53 von Matze.)
|
Matze
LVF-Team
Beiträge: 1.027
Registriert seit: Apr 2010
20xx
2010
DE_EN
7xxxx
Deutschland
|
Wie auf eine Instanz aus parallelen Prozessen zugreifen?
Hallo,
vielen Dank für den sehr ausführlichen Beitrag. Ganz so ausführlich hätte ich das nicht gebraucht, aber so lernen andere auch was.
' schrieb:Ja, hier sehe ich auch ein Problem. Das lässt sich aber minimieren, indem der eine Prozess nur in einem bestimmten Raster arbeitet. Zudem sollte die Queue so kurz wie möglich leer sein. [*nachdenk*] Hier sehe ich aber auch ein Problem.
Ich sehe vor allem das Problem darin, dass es mir dann alle Schleifen synchronisiert. Zumindest vermute ich das. Und das bringt mir absolut nichts, da diese unterschiedlich schnell laufen sollen.
' schrieb:Ich verwende meine MöchteGernKlassen wie folgt [...]
Und ich wie folgt: Klasse raus, Melder genommen, fertig. Mir war das nun irgendwie zu doof und das mit der Klasse hat alles nicht geklappt. Ich habe schon den halben Tag damit vergeudet und wollte dann endlich Fortschritte sehen. Ein Melder ist zwar suboptimal in meinem Fall, aber LabVIEW hat eben auch seine Grenzen.
Falls jemand ein simples Beispiel hat, wie man das mit einer Klasse lösen kann ohne umständliche Workarounds (2. Klasse zur Organisation der Queue o.ä.), dann wäre das nett. Also eine einfache und ordentliche Lösung.
D.h. Instanz erstellen und in mehreren parallelen Schleifen, die alle unterschiedlich schnell sind, darauf zuzugreifen und Werte zu verändern. z.B. dass eine Schleife schreibend darauf zugreift und alle anderen lesend. Im Idealfall dann noch ohne Melder.
Ich lerne immer gerne dazu.
Grüße
|
|
|
06.12.2010, 22:09
(Dieser Beitrag wurde zuletzt bearbeitet: 06.12.2010 22:09 von abrissbirne.)
|
|
|
06.12.2010, 22:17
|
unicorn
LVF-Freak
Beiträge: 680
Registriert seit: Jul 2009
8.6.1, 2010 - 2012
1994
EN
10xxx
Deutschland
|
Wie auf eine Instanz aus parallelen Prozessen zugreifen?
Statt der äußeren Klasse kann man die Queue auch direkt verwenden. An allen Stellen wo die Klasse aus der Queue genommen wird könnte man ja erst prüfen, ob die Klasse drin, und anderenfalls warten (über das timeout). Solange gewartet wird, braucht es nicht viel Rechenzeit, so dass diese dem Task zur Verfügung steht, der die Klasse gerade ausgecheckt hat. Das sollte auch der Fall sein, wenn man direkt versucht, die Klasse aus der Queue zu holen (Ich bin da aber nicht 100%ig sicher).
Ich denke, man kann das gleiche Verhalten über eine FGV programmieren:
Case "auschecken": Falls ausgecheckt, dann 50 ms warten, anderenfalls Klasse herausrücken,
Case "einchecken": Boolean "Klasse ausgecheckt" auf FALSE setzen und Klasse und Boolean mittels Shift-Register speichern.
Dann noch ein Case "Init" und einen zum Aufräumen
|
|
|
06.12.2010, 23:21
|
IchSelbst
LVF-Guru
Beiträge: 3.700
Registriert seit: Feb 2005
11, 14, 15, 17, 18
-
DE
97437
Deutschland
|
Wie auf eine Instanz aus parallelen Prozessen zugreifen?
' schrieb:aber so lernen andere auch was.
Zitat:Falls jemand ein simples Beispiel hat, wie man das mit einer Klasse lösen kann ohne umständliche Workarounds (2. Klasse zur Organisation der Queue o.ä.),
Das wird nicht gehen. Da gibt es auch in einer strukturierten Sprache große Probleme.
Das Problem liegt darin, wenn mehrere (z.B. 8) (wenn auch nur quasi-)gleichzeitig einen Parameter beschreiben wollen. Es kann aber nur ein einziger der 8 einen Wert speichern. D.h. also, 7 würden umsonst gearbeitet haben. Besonders kritisch wird es dann, wenn vor dem Schreiben ein Wert ausgelesen werden muss, um eine Berechnung des zu schreibenden Wertes durchführen zu können. Dann entsteht ein Zeitraum, während dessen ein Zugriff auf die Klasse verboten werden muss. In einer Single-Thread-Applikation ist das einfach: Da geht so wie so nur eins nach dem anderen. In einer Multi-Thread-Applikation jedoch müssen Vorkehrungen getroffen werden, die ein Unterbrechen kritischer Vorgänge verhindern. Ich weis (aus Debug-Fenstern), dass es in strukturierten Sprachen solche Möglichkeiten gibt.
Auch in LabVIEW gibt es solche Möglichkeiten: Klasse in Queue legen. Die Lösung mit der Queue ist in so fern hervorragend, weil die komplette Klasse mit allen Methoden sowie private und public Data mit nur einem einzigen "Befehl" geschützt werden kann.
[*grübel*]
Die Queue hat nur einen Nachteil: Man kann kein SubVI machen, das kontinuierlich läuft und die Klassen-Daten kontinuierlich manipuliert. Irgendwann muss dieses SubVI nämlich stoppen und die Klasse für eine bestimmte Zeit in die Queue legen - wie sonst sollten andere die Klasse verwenden können.
Jeder, der zur wahren Erkenntnis hindurchdringen will, muss den Berg Schwierigkeit alleine erklimmen (Helen Keller).
|
|
|
| |