(24.07.2018 10:05 )seuk schrieb: Du schreibst, man könnte im einfachsten Fall aber auch die AF Funktion 'Read Caller Enqueuer' verwenden, um die Nachricht einfach immer an den Aufufer (des Akteurs, wenn ich richtig liege) zu senden.
Auf welchen Abschnitt der Anleitung beziehst Du Dich genau. Ich kann diese Aussage an der Stelle, an der ich das VI Beschreibe nicht finden.
(24.07.2018 10:05 )seuk schrieb: Nun noch eine allgemeine Frage: Es wird darauf hingewiesen, dass man im Normalfall immer die Baumstruktur bei der Kommunikation einhalten soll. Wollen zwei Akteuere also miteinander reden, muss die Nachricht im schlechtesten Fall einige Ebenen hoch bis zum Hauptakteur und dann wieder runter bis zum Empfängerakteur gereicht werden. Gibt es ein Beispiel, in dem das geschieht? Wie adressiert man dem Empfänger und wie findet die Nachricht ihren Weg? Oder bin ich hier vom Verständnis noch auf dem Holzweg?
Im Dokument ‚Actor Framework.html‘ werden im Abschnitt ‚Message Queues‘ die vorgesehenen Möglichkeiten zum Versenden von Messages dargestellt.
Ganz allgemein sollte beim OO-Design das Geheimnisprinzip gewahrt werden. Wenn die Message-Enqueuer an andere Aktoren verraten werden, ist der Determinismus des Message-Flows nicht mehr gewährleistet, Verantwortlichkeiten sind nicht mehr eindeutig verteilt und das Debugging wird deutlich erschwert. Daher die dringende Empfehlung von den NI AF Entwicklern Nachrichten nur entlang der gegebenen Hierarchie von Nested-Aktoren zu senden. Wenn davon Abgewichen wird, und dafür kann es gute Gründer geben, sollte man sich dieser Gründe bewusst sein und sich entsprechend gut dokumentieren.
(24.07.2018 10:05 )seuk schrieb: Wenn ich diese Funktion im Do.vi der Message platziere erhalte ich von LabView folgende Fehlermeldung
Die Message-Klasse ‚UPNCalculator Actor.lvlib:Preview Stack Msg.lvclass‘ ist zwar Teil der lvlib, allerdings nicht Teil der Aktor-Klasse ‚UPNCalculator Actor.lvlib:UPNCalculator.lvclass‘.
Daher führt der Aufruf von 'Read Caller Enqueuer' in ‚UPNCalculator Actor.lvlib:Preview Stack Msg.lvclass.Do.vi‘ zum Fehler.
Wenn der Stack an den Caller-Enqueuer des UPN-Calculator-Aktor gesenden werden soll, müsste dafür eine extra öffentliche Zugriffsmethode für den Caller-Enqueuer bereitgestellt werden oder das Versenden schon in dem ‚Preview Stack.vi‘ passieren.
Wie dem Namen des virtuellen Verzeichnis schon zu entnehmen ist, soll diese Nachricht ja aber als Callback von der Sender-Klasse der Nachricht, also hier dem GUI als Kindklasse implementiert werden, weil ja nur das GUI weis was es mit dem empfangenen Stack tun soll, nämlich den Stack auf dem FP anzuzeigen.
(24.07.2018 10:05 )seuk schrieb: In Übung 7 soll ein "unerwarteter Zustand" gezeigt werden, wenn die beiden Akteure den gleichen Rechner verwenden. Ich vermute, was gemeint ist, ist dass die Testberechnung zu einer Veränderung des Stacks führt, von der die GUI so erstmal nichts mitbekommen hat...
Richtig.
(24.07.2018 10:05 )seuk schrieb: Aber bevor ich mir das ansehen kann schmiert mir LabView ab.
Aber was bedeutet hier LabVIEW schmiert ab? Die Applikation beendet sich mit Fehlermeldung, und wenn ja mit welcher? Oder crasht LabVIEW? Das sollte nicht passieren.
(24.07.2018 10:05 )seuk schrieb: Das Problem: Wir haben im Do-Teil der Nachricht das Send Preview Stack VI getauscht.
Nun wird der Stack zurück an die UPNCGUI geschickt und nicht mehr an den Calculator. Löse ich nun die Testberechnung aus landet der Self Enqueuer von 'Calculator.lvclass' in der falschen Klasse 'UPNCalculatorGUI.lvclass', oder so ähnlich...?
Das ist vermutlich mit der Auswahl des Enqueuers beim Senden schiefgegangen. Ich habe hier bei mir natürlich nur die fertige Version. Deine Zwischenstände beim Dimplementieren der Übung kenn ich ja nicht, kann daher auch nicht mehr dazu raten.
(24.07.2018 10:05 )seuk schrieb: Vorausgesetzt, man möchte den gleichen Actor für verschiedene GUIs gleichzeitig nutzen. Wie erreicht man also, dass der Empfänger einer Nachricht, seine Daten an einen beliebigen Aufrufer zurückgibt? *kopfkratz*
- Ich könnte im UPNC für jeden Aufrufer eine eigene Nachricht anlegen, welche dann genau weiß, an wen sie die Daten zurück zu schicken hat. Das scheint mir aber nicht sehr flexibel zu sein.
Das nennt man starke Kopplung und ist in der Tat sehr unflexibel. Es gibt zum Thema Vorträge die zeigen wie man schwache Kopplung implementieren kann. Siehe meine VIP Vorträge zum Thema AF.
(24.07.2018 10:05 )seuk schrieb: - Ich würde lieber das Send Preview Stack.vi überschreiben, so dass je nach Klasse des Aufrufers unterschiedliche VIs aufgerufen werden. Doch dabei habe gedanklich noch so meine Probleme. Ich definiere eine Nachrichtenklasse CalculatorUserMsg mit einer leeren Methode 'Send Preview Stack' (also für Override), welche ich in das Do.vi einfüge, diese Klasse muss vom AF-Message erben. Die Messageklassen der beiden Aufrufer erben dann von CalculatorUserMsg und implementieren ihre jeweiligen "Empfangsmethoden" für den Stack, wie gehabt. Ich dachte das klingt nach einem guten Plan. Doch dann schaute ich auf das VI.
Bild...
Das Send Preview Stack VI hat ja gar keine Inputs, anhand deren entschieden werden könnte, von welcher Klasse die entsprechende Methode nun aufgerufen werden soll. Aber durch Vererbung und Überschreiben der Methode sollte das Problem doch lösbar sein, oder? Vielleicht hat hier jemand einen Tipp für mich :-)
Dieses Problem ist durch Vererbung nicht lösbar, weil sich GUIs und Aktoren, die etwas bestimmtes tun, selten in derselben Vererbungslinie befinden, sondern eher verschiedenen Elternklassen haben.
(24.07.2018 10:05 )seuk schrieb: - Oder man baut den Ansatz vom Self Enqueuer weiter aus: Der Aufrufer übergibt nicht nur dessen Referenz, er übergibt zusätzlich auch eine Info, welche Nachricht für die Rückantwort verwendet werden soll. Hier habe ich aber leider keine Ahnung, wie man das implementieren könnte.
Diese Idee ist die Erfolg versprechende. Der Sender einer Nachricht, der das Resultat einer Aktion des adressierten Aktors asynchron zurückerhalten möchte, muss also zusätzlich zu seinem eigenen Self-Enqueuer die Callback-Message, eine Kindklasse der Empfänger-Nachricht, an den Empfänger übergeben, die dann von ihm an den Sender ursprünglichen Sender (Anforderer) zurück gesendet un in seinem Scope ausgeführt wird. Also von hinten durch die Brust ins Auge.
Einen allgemeinen Lösungsansatz für dieses Problem haben wir in das CS++ eingebaut. Es handelt sich um die CSPP_AsyncCallbackMsg von der alle anderen CS++Messages erben. Mit diesem Trick kann zu jeder CS++Message eine asynchrone Callback-Message erstellt werden.
Eine Bespielimplementierung findet man in dem CS++ Beispielprojekt,
https://git.gsi.de/EE-LV/CSPP/CSPP. Es geht um die Aktoren CSPP_InstrSim und CSPP_InstrSimCtrl.
Ich hoffe, hiermit etwas Licht in Dunkle gebracht zu haben.
Gruß Holger