01-30-2023 08:01 AM
Hello again
In the past i've mostly used Action Engines to pass things (Configure, Command, Data info) around. Recently i started looking into LabVIEW classes and while i get most of it, i don't really get how you pass the data around subVIs or asynchronously called subVIs. With AE you just drop the AE in the subVI and you have the data, but with classes if i understand correctly, doing this would create new instance of the class.
So, how do?
01-30-2023 01:49 PM - edited 01-30-2023 01:54 PM
Think of classes as special clusters, because they are. Anything you do to pass clusters around is the same thing you do with classes.
I avoid FGs/AEs as much as possible unless I know I'm designing something I'll only ever need a singleton for so my preferred way to send things to async VIs is to use notifiers/queues/events with async VIs. You can put controls for the mechanisms on the front panel of the async VI, or group them into clusters and pass them into the async call. Create the notifiers outside of the async VI and then the calling hierarchy can use it to pass into the async VI.
Edit to add: Classes in LV aren't like classes in other languages where they're references or pointers to them get passed around. LV Classes follow LV's dataflow paradigm and are just containers for data with all the same handling as clusters but with extra functionality for access scoping.
01-30-2023 02:40 PM
As IlluminatedG pointed out, in LabVIEW classes are at some level just fancy clusters with data and inheritance rules attached to them. There's a write up from NI on why they made some of these decisions that is worth reading. That having been said... LabVIEW classes being passed by value instead of reference does make some things a bit hazy.
I assume that the jist of your question is that you have a single object that you wish multiple asynchronous threads to be able to act on? If that is the case, there are certainly problems with an action engine.
The answer I want to give is "well, just refactor your program so that you don't need to do this". I have often slung objects around through queues or notifiers where I expect and understand that I'm passing by value, not by reference. Whatever asynchronous process needs to modify that object will do so and then pass it on to the next process or location that is expecting it. In fact, this is basically how the actor framework works!
However, sometimes you're too far into a project to realistically refactor, or there are cases where you really do want one object being acted on by multiple threads (a heartbeat monitor for example). In this case, it is possible to store the object inside of a Data Value Reference (DVR). I've done a few different takes on this over the years, but you can get the basics in this article.
Hopefully this helps
01-31-2023 01:53 AM
@BowenM wrote:The answer I want to give is "well, just refactor your program so that you don't need to do this".
The program will stay as is for now, i'm asking because i'm trying to learn new things for future projects, but i don't really have any experience with other sufficiently large projects than the one i inherited.
This project uses state machine subVIs (asynchronously called) which receive commands and collect/process data, they do this with the use of AEs. The state machine subVIs basically deal with VISA communication, regulation, DAQ etc.
I'll look into the Actor Framework, thanks.