LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Why use queue to stop parallel loops?

argh, too late to edit the reply.

 

I added an indicator in the calling VI that reacts to events in the subVI, specifically an LED that is lit if the mouse is inside the subVI's pane.  interesting side effect: the event fires even if the subVI finishes.

-Barrett
CLD
Download All
0 Kudos
Message 11 of 21
(2,633 Views)

You can also pass the reference of the top-level vi to the subVi and register for the FP Close? event. (or even try to get the ref from inside the subVI).

Note: I didn't look at your code.

 

Felix

0 Kudos
Message 12 of 21
(2,612 Views)

Very impressive!  I was puzzled why stopping the sub-VI left its front panel open (allowing the Mouse Over SubVI Panel indicator to work), then realized it was set in the VI's Window Appearance (and having the window close on exit left the Mouse Over indicator in the "on" state).

0 Kudos
Message 13 of 21
(2,600 Views)

@Daklu wrote:

@aeastet wrote:

I can assure you that an event structure in a sub vi can be read and can send events back to the main vi. This is easy to do and very flexible.


 

Please post an example of an event structure in a sub vi handling a front panel event, such as a button press, on the calling vi.  I'm very interested in seeing it.

 

...


Hi Daklu,

 

THis app has two operating modes (Collect and Analyze) where there are distinct sets of controls for each. When in on mode the other set of controls should be ignored completely.

 

2_Init_GUI_Controller.PNG

Inside Analyze I register for the events required to support that mode as shown below.

 

7_Get_Refs_In_Use.PNG

 

Aside from the easy overview of what is handled in this mode I also free myself from issue with users punching buttons for the other mode (no need to track mode internally to dicide if i should act or not).

 

more often that not these days, the larger apps don't get an event structure and they act as a container for the FP object and mode control code.

 

Prior to Dynamic event registration my top level GUI could have dozens of events to handle all of the modes.

 

I find this easier to code develop and teach to my customers (since they are the ones who will have to maintan it).

 

Your thoughts are highly valued so plese "let er fly"!

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
Message 14 of 21
(2,598 Views)

@Felix: aha, thanks, I hadn't thought of registering the caller's VI ref for FP close in the subvi.  So the example I posted could skip the user event altogether and handle the top level's FP close? in both VIs (but then it wouldnt have an example of passing user events around!).

 

two things:  

-never wire the same "register for events" refnum to two different event structures.  The event structures can deadlock.

-a null user event reference (running the subvi on its own) wired into the register for events hangs the event structure, with no error from the register node.  (a bug?)

 

@Bob: right, the subVI is set to "show when called" (so you can see its indicators) but not "close if wasn't open" (so you can see the events firing for a stopped VI.)

 

 

-Barrett
CLD
0 Kudos
Message 15 of 21
(2,582 Views)

My standard modus operandi is to use queues for point to point things and event structures for broadcast things.  This ends up meaning most loops are run by queues with a few things, such as global stop, handled by event structures.  Queues are generally much faster than event structures, but this does not usually matter for anything but the most demanding of applications.  The fact that you can directly manipulate the queue elements, but cannot do the same for event structures, is a major reason I prefer it for most operations.  I consider it more flexible, but this is a personal preference.

0 Kudos
Message 16 of 21
(2,570 Views)

 


@DFGray wrote:

My standard modus operandi is to use queues for point to point things and event structures for broadcast things.


 

I've come to much the same conclusion.  It was hard getting away from the Guideline "Do not put more than one Event Structure in your VI." (LabVIEW for Everyone, Third Edition, but probably will be "updated" for the Fourth Edition), but I'm now signalling between loops and (I think) safely stopping them using dual User Events (the Front Panel Event loop sees the Stop button, sends a "Please Shutdown" user event to the Main Loop, which does all kinds of cleanup, then sends an "Exit" user event back to the Front Panel loop to get it to wire True to its Stop terminal).  Very straight-forward, easy to understand (and explain) (and remember "Why did I do this?" six months from now).

 

BS

0 Kudos
Message 17 of 21
(2,547 Views)

Thanks to all (especially blawson) for the examples.  I stand corrected--it is indeed possible.  When I was playing around with passing a button reference through the front panel terminal before posting yesterday I wasn't getting events based on the calling vi's control, only in response to events on the reference number control on the sub vi.  I don't have the sample I was playing with so I can't compare it with blawson's code to see what's different.  (I do specifically remember changing my sub vi's control reference input terminal to strictly typed broke the calling code, even though to the best of my recollection the code was otherwise identical.)

 

I see blawson's example passes an Event Reg Refnum to the sub vi.  To be honest I had completely forgot about that.  (And this is after building a drop-in reusable event manager library last year!)  I actually have done that before but found it to generally be more trouble than it's worth during development due to the hassle of changing them.  Putting event reg refnums on the connector pane hinders flexibility even more than putting enums on the connector pane does.  You can't change any of the events or add new events without breaking code all over the place.  That's okay if you have all the dependent vi's in memory when you change it, but you may be in for a nasty surprise if they are not.

 

So yep, I was wrong about a sub-vi triggering on a parent's front panel events.  However, looking at the example I was doubtful that a queue-based implementation would be more complicated than an implementation that requires a user event refnum, a control refnum, and an event reg refnum, so I refactored the example and posted it below.  It has the exact same functionality as the original code with the a couple exceptions:

 

1.  The top level vi doesn't continue receiving the sub vi's MouseEnter and MouseExit events after it has stopped.  (That strikes me as really weird behavior... has anyone used that feature in a customer's application?)

2.  The sub vi doesn't close itself--it sends a message to the calling vi asking if it can close.  If the calling vi says it's okay, then it sends a message back to the sub vi telling it to close.  I like to use this messaging pattern in parallel code modules that are designed for one caller at a time as it allows more flexibility (and therefore reusability) in how the module can be used.  I included it here for kicks and grins.

 

Whether or not it's more complicated depends on what you're used to I guess.  To me the queue implementation is more easily understood.  I believe it is--without question--a more flexible solution than passing fp control refs or fp event reg refnums.  Messages can come from any source, not just front panel events.  They can also carry with them any data, not just the data associated with that particular event.  The flexibility of being able to easily send what information I want, when I want to send it, is extremely valuable.

 

I also believe messaging with queues is a more scalable solution.  Code that starts out in a parallel loop on the same block diagram can very easily be converted to a sub vi as more functionality is added.  Later you can make it into a class or an actor object.  Through all of those changes and added functionality the data type to communicate with that bit of code hasn't changed.  It's still a queue for a message that has a name and data.  (I confess I don't use string/variant messages anymore.  I use an object-based messaging library that provides better type safety than the string/variant and includes error handling.)

 

 


Ben wrote:

Your thoughts are highly valued so plese "let er fly"!


 

Aww... now you're just trying to sweet talk me... 😉

 

When I'm developing an application I try to be very careful about managing dependencies between code modules and monitoring how complete each of those modules are.  Stable modules (those that are finished) should never depend on unstable modules (those that have uncertain requirements.)  If I have a stable module that depends on an unstable module then I run a high risk of having to change the code in my stable module when the unstable module's requirements change.  In the worst cases all the prior work I've done developing and testing the stable module is wasted.

 

User interfaces are the most volitile aspect of the applications I develop.  Users ask for all sorts of changes late in the project.  Passing UI control references to the sub vis makes the application's functional code, which should be stablized, dependent on the UI, which is likely to change.  When that happens changes to the UI often have a trickle down effect all the way into the lowest level sub vis.

 

I got tired of fighting that battle, so now user interfaces are the last thing I create.  The UI is usually a thin wrapper that converts front panel actions into messages for the functional code and messages from the functional code into actions on the front panel.  (Very similar to what is shown in "Top level - Queue.vi.")  As an added bonus it is much easier to test functional code when it isn't dependent on a user interface.

 

 


Ben wrote:

I find this easier to code develop and teach to my customers (since they are the ones who will have to maintan it).


 

Thankfully this isn't one of my requirements.  Flexibility requires abstraction, and if your customers will have a difficult time maintaining the code because it has more abstraction than they are used to, then you probably ought to use an architecture they will understand even if it compromises your/their ability to easily make changes in the future.

 

I'm not claiming using messages (via queue or user events) to communicate between parallel threads is always the right decision; that depends on the project requirements.  I am claiming if modularity, flexibility, and scalability are your goals, messages are the way to go.  Everything else is a compromise.  My philosophy is to maintain as much flexibility as long as possible given the project contraints.  Decoupling code modules and using messages to communicate go a long ways towards achieving that goal.

Download All
Message 18 of 21
(2,537 Views)

 


Daklu wrote:

...

I see blawson's example passes an Event Reg Refnum to the sub vi.  To be honest I had completely forgot about that.  (And this is after building a drop-in reusable event manager library last year!)  I actually have done that before but found it to generally be more trouble than it's worth during development due to the hassle of changing them.  Putting event reg refnums on the connector pane hinders flexibility even more than putting enums on the connector pane does.  You can't change any of the events or add new events without breaking code all over the place.  That's okay if you have all the dependent vi's in memory when you change it, but you may be in for a nasty surprise if they are not.

 


 

 

There shouldn't be any problem with event reg refnums and enums (and queue refnums, etc.) if they are type defined.  User or dynamic events can break if you delete something from the registration node that is handled in the event structure, but the equivalent in a queue would be something like adding an element to an enum that the queue feeds to a case structure, or deleting an element from the queue element's cluster without removing unbundles where it was referenced - if you do these things you know there will be cleanup to do (and you know generally where it is).  If you don't typedefine things you pass around a lot that could be revised, it's going to be fragile no matter what the architecture.

 

 


 

So yep, I was wrong about a sub-vi triggering on a parent's front panel events.  However, looking at the example I was doubtful that a queue-based implementation would be more complicated than an implementation that requires a user event refnum, a control refnum, and an event reg refnum, so I refactored the example and posted it below.  It has the exact same functionality as the original code with the a couple exceptions:


 

 

This is really just a proof-of-concept example, and the event setup can be cleaned up to be simpler as well: the user event is unnecessary (pass the VI reference instead).  I agree that a queue is simpler and more natural for passing messages around but this is useful stuff when you're a) using dynamic event registration (Ben's example) b) sending messages to an event loop or c) broadcasting messages losslessly.

 


 

 1.  The top level vi doesn't continue receiving the sub vi's MouseEnter and MouseExit events after it has stopped.  (That strikes me as really weird behavior... has anyone used that feature in a customer's application?)


 

 

It is weird, I kind of like it.  I cannot imagine any reason I would want a stopped front panel to stick around so the user can interact with it in an executable, but maybe this could have a scripting application... it seems like it might be possible to have a VI running that could react to events on a FP or BD you have open for editing...

 


 

They can also carry with them any data, not just the data associated with that particular event.  The flexibility of being able to easily send what information I want, when I want to send it, is extremely valuable.


 

 

I know you mean the control events, but that flexibility exists with user events... think of these like the string/variant (or enum/variant) queue types, except that the data element label *is* the enum and the data element is the variant data without need for converting. It *is* a queue, albeit one you can't access or reorder.  I wouldn't choose to replace a queue-based message setup with a user-event based one mostly because there will probably come a point when I need to add something that requires inspecting the Q for duplicate messages, prioritizing messages, etc.  On the other hand, using it as an any-to-many queue is great.

 


 

-Barrett
CLD
0 Kudos
Message 19 of 21
(2,525 Views)

There shouldn't be any problem with event reg refnums and enums (and queue refnums, etc.) if they are type defined... 


 

Typedefs (especially enums) still only work well when everything that uses them is loaded into memory.  An unloaded vi's response to a typedef edit depends on the specific edits you made.  Sometimes wires will be broken; sometimes they won't be broken but the behavior will change.  Add an item, reorder a few items, change a name... *poof* new bugs just appeared in code you aren't even editing. 

 

Typedefs are super convenient.  They also aren't very flexible and get in the way when creating modular code.  Reusable code trades in some type safety in exchange for flexibility.  The goal is to create a module with an api that is well-defined enough to be easy to use and flexible enough to accomodate future additions.  Typedefs are all about type safety and not at all about flexibility.  For that reason I almost never expose a typedef outside of a class or lvlib.  In fact, I rarely use typedefs at all anymore; classes are a much better alternative for my work.

 

I have, however, used a typedef event reg refnum with user events and still found it to be a royal pain in the neck.  Every time I wanted to add a new message (event) I had to wire in the new user event, create a new constant from the reg for events prim, copy the constant over to the ctl, and save the ctl file.  I found this really disrupted my development flow.  YMMV.  I'm not saying user events are bad.  I like them a lot and use them frequently.  I'm just saying I don't like passing event reg refnums between sub vis because of the overhead in making changes and their overall lack of flexibility. 

 

 


This is really just a proof-of-concept example


 

Yep, I know.  I didn't make it clear that I wasn't trying to critique your code specifically, but rather the idea that using front panel events is easier than a queue while still being as flexible, scalable, and modular as a queue-based messaging system.  My apologies.  (I will say I don't consider passing a vi ref instead of a user event an improvement.  🙂  )

 

 


this is useful stuff when you're a) using dynamic event registration (Ben's example) b) sending messages to an event loop or c) broadcasting messages losslessly


 

The "problem"*** with Ben's code is that the app's functionality, Analysis_Mode.vi, is very tightly coupled to the user interface.  What happens if the client wants the same functionality on a different test station but with a slightly different UI?  Or perhaps they want to disable certain kinds of functionality when the night technicians are on duty.  In order to make those changes he has to modify the app's functional code, which creates an opportunity for new bugs to appear and requires a new round of software test and validation. 

 

If the UI were decoupled from the functional code those changes can be implemented in the UI code and the functional code will remain untouched.  With a decoupled UI you can create completely separate UI modules, each of which uses the same functional code.  Maybe you have a detailed UI for operators on the floor and a simplified status UI plant managers can bring up from their desk.  A messaging system gives you an upgrade path to (relatively) easily implement these requirements should they come up later on.  Having your functional code directly register fp events does not.  Eventually it will collapse under the weight of all the extra code implemented to work around the decision to use fp references in the first place.

 

Points b) and c) look like they refer to user events, which I like and use.  My issue isn't with events in general or the event structure; it's with using UI components in functional code.  The OP's question appeared to be about controlling parallel loops in general, not about controlling parallel loops on a user interface vi.  Controlling parallel loops via fp events is okay for certain situations.  For the reasons I've explained in this thread I don't believe it is a good general purpose solution to the problem.  Every design decision has trade-offs.  Our job as developers is to make the best decisions based on the customer's requirements.  We can't make correct decisions if we don't understand the consequences of the choices available.

 

 

***By "problem" I don't mean to imply Ben's code is wrong or bad.  In fact it is exceedingly neat, clear, and it meets his customer's requirements.  (Which after all is the whole point.)  The "problem" I'm referring to is simply what is being lost in flexibility, modularity, and extendability by using that technique.

0 Kudos
Message 20 of 21
(2,502 Views)