I am viewing source code of Actor Framework Demo. I have a question when I opening "Actor core.vi" of "Feedback Cooler Pretty UI.lvclass".
It calls "Send New Temp Threshold.vi" to set the temp threshold as below.
And I open the Do.vi of "Change Coolder Threshold Message.lvclass", it just calls "Write threshold Temperature.vi" of "Feedback Cooler.lvclass" as below.
My question is why not it calls "Write threshold Temperature.vi" of "Feedback Cooler.lvclass" directly in "Actor core.vi" of "Feedback Cooler Pretty UI.lvclass" as below.
Solved! Go to Solution.
The "Actor" objects are "by-value", not "by-reference", meaning that when you branched the Actor wire you duplicated the Actor. Thus the Actor you called the method on is a different Actor than the one passed to the Actor Core parent. So this wont work. You could call the "Write threshold Temperature.vi" method BEFORE passing the Actor to the Actor Core parent, but not after. Note that this is different that the various Queue objects, which are effectively references which can be branched and used in many places while always referring to the same queue.
To add to what James said. You have to remember that once launched the Actors are running in their own process loop. By default (and good data flow design*), their private data is not shared with anyone. You can set the data prior to launch but after that, the Actor is essentially held in a shift register in Actor Core.vi and access to the private data can only happen when a Message's Do.vi is invoked.
If the VI that launched the Actor forks a wire prior to the launch, it now has a copy of the launched actor. If you look at Launch Actor.vi you will notice that Actor is an input terminal and not an output. What you get is effectively the queue of the Actor just launched. "Out of the box" that is the only way to communicate with the launched Actor.
* there are valid reasons to share data, but they come with risks. You can use data value references, shared variables, globals, etc., but all circumvent the data flow paradigm.
Hope this helps,
To add more, now that I studied your block diagram a bit more and I can see how one might get confused.
Note that the base Actor Core.vi is a process loop, and as I mentioned the 'state' of the actor is held in the shift registers of its message loop.
While the original Threshold Cooler UI.vi branched the wire leading to the base Actor Core.vi, it only did so in order to get its own queue.
The branch you added was fed to the UI Event loop with the intent to set values. The event loop is an independent loop from the loop in actor core. And what you fed it was a snapshot of the Feedback Cooler UI.
In both cases you should think of these as copies of the Actor that was sent to base Actor Core.vi. Any changes made to the Actor will be on the 'local' branched copy. That goes for the changes made within base Actor Core.vi from handling a message. Those changes will not be visible in the event loop.
You could have the Private Data Cluster of Feedback Cooler UI include a DVR (data value reference) and then you could have the UI Event loop call the Set_X directly, but as I said that brings risks. This demo kind of did the reverse - it shared the control refnums with the message loop. I personally prefer to have DVRs in my private data in this situation - where multiple loops exist for a single instance of an Actor. One loop is handling the messages, and the other is handling the events. There is a bit of coordination between the two and certainly some maintenance of the DVR (create/destroy).
No mater how you look at it, somehow you have to share data between the two loops - messages, events, DVR, etc.
Again, I hope this helps.