LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Master/Slave with Events

Solved!
Go to solution

Hi, I am developing an application in which user actions will initiate ceratin events.  I have implemented the app as an event-driven state machine.  However, I realized that one of the events needs to kick off a continuous process, i.e. reading from the buffer of a USB device.  It seems that the Master/Slave pattern would apply.  Is it possible to implement the Master/Slave pattern with the slave activity triggered by an event?  I have a feeling these two design patterns are incompatible.

 

Thanks,

-Jamie

0 Kudos
Message 1 of 18
(4,799 Views)

Yes.  The queue or notifier you are using to fire off the slave loop, you only enqueue in the particular event case.

Message 2 of 18
(4,790 Views)

@jfalesi wrote:

Is it possible to implement the Master/Slave pattern with the slave activity triggered by an event?  I have a feeling these two design patterns are incompatible.


There is nothing that says you can't mix multiple design patters.  I do this sort of thing all the time.  I usually have one main loop that is a state machine and then I have several modules that are a derivative of the Queued Message Handler.  The main state machine just sends the commands to the other loops as needed via a queue, notifier, or user events.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
Message 3 of 18
(4,778 Views)

I guess I'm not quite sure what I'm doing yet... I didn't realize I had a Queued Message Handler.  I just have an Event structure...

 

I thought that a particular event pane had to execute completely before any user action would trigger another event...

 

Most of my event structure panes look like the attached image.

 

 

0 Kudos
Message 4 of 18
(4,770 Views)

You talked about master/slave.  That implies two loops, a master loop and a slave loop.  Generally this type of architecture is called producer/consumer.  It can also be called master/slave with the only difference being semantics.

 

If you create a queue to send data or commands, one loop can enqueue the data (such as inside an event of your event structure), the other loop can sit there waiting for the data to arrive.

Message 5 of 18
(4,760 Views)
Solution
Accepted by topic author jfalesi

If I am interpreting your one concern right, "I thought that a particular event pane had to execute completely before any user action would trigger another event...":

 

An Event Structure maintains a queue of its unhandled events.  When any event that an Event Structure is registered for is raised, LabVIEW enqueues the event in that Event Structure's queue (you can have multiple registrations for the same event, and LabVIEW will enqueue a copy of the event in each registration ... a bit more advanced but it comes up most often with User Events, since you normally shouldn't have multiple Event Structures present for a single VI).  When the Event Structure is called, it will dequeue the next unhandled event and execute the corresponding diagram.  If there are no events in its queue, then it will wait.  If no events occur (are added to its queue) by the time the timeout has elapsed, then the Timeout diagram is executed.

 

What this means is, the diagram associated with a certain event would have to complete before any other diagrams can possibly execute; however, events, such as pressing buttons on the UI, are still captured while the first diagram is executing.

 

 

If your Event Structure diagrams don't have long-running code, then you can get away with having that be your only design.  For example, the find and initialize operations in your attached image sound like things that would just need to happen once and return relatively quickly, so the Discover Slave Device button will probably operate as you expect - a slave is discovered and then initialized upon pressing the button, after which your VI is ready to execute more event diagrams.  However, if one of your states is actually running persistent operations, such as a "Run Slave" diagram where you have a persistent data collection loop, then you will be in trouble since that diagram will not complete and your UI will probably become unresponsive.

 

What does work is if the persistent operations are ran asynchronously.  If your slave has something like a "Start ANT Slave.vi" that starts some asynchronous slave process for you and then returns, similar to how I expect the "Init ANT Slave.vi" to behave, then that would work.

What RavensFan and crossrulz were mentioning are ways to achieve this in your design (rather than in the design of the ANT Slave class).  Say that your ANT Slave class does not have any internal asynchronous stuff set up that you can simply start, and you are going to have to do all of the running operations on your block diagram yourself.  In that situation, you could create a new while loop parallel to your current one.  Some form of synchronization mechanism, such as a Notifier, could be acquired and passed to both loops.  The slave run loop could simply wait on the Notifier before it does anything.  Then in an event handled in the upper loop for pressing a start button for example, you would send a Notifier, indicating, "Okay slave loop, please start".  The slave would start its operations and continue to run them, while your event diagram in the first loop would finish and you would still have a responsive UI.

 

The Queued Message Handler design pattern is where you have a Queue instead of the Notifier used in the example above, and you can enqueue messages that you want the slave to receive (and ostensibly act upon).  Then the slave's loop would check the queue to see if its master has sent anything - if so, then it performs that action ; if not, then it performs whatever action it deems appropriate.



Message 6 of 18
(4,743 Views)

Example:

MasterSlave_with_Events__Example.png

 

I also attached a copy of the VI itself in case you don't have a compatible version to drop this snippet into, you can get someone to convert that for you.



Message 7 of 18
(4,726 Views)

Yup, combining an event structure with a master/slave is an excellent architecture, IMO. Good way to perform significant  processing without holding up the event loop and locking the GUI, IMO.

Message 8 of 18
(4,692 Views)

Wow, thanks for the detailed response.  I now see how I can combine the two design patterns.  I was planning to put the continous loop for reading from the ANT USB device in the main VI as opposed to the ANT Slave class, because occasionally processed data from the ANT USB buffer will be used to update GUI information in the main VI.  Is there a way to achieve this with notifications/events if the continuous loop is in the ANT Slave class?

0 Kudos
Message 9 of 18
(4,641 Views)

Another question - is there an advantage to using an Event structure instead of a Case structure inside the consumer loop?

0 Kudos
Message 10 of 18
(4,634 Views)