LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

I need something like a Queue but different


@Mancho00 wrote:

@RTSLVU wrote:

 

You are right I do not understand them at all and in all of the User Events examples "events" are generated by an event structure that is triggered by the user changing the state of a front panel control. 

User Events aren't generated by an event structure.  An event structure is registered for the event, so when the event is generated anywhere in the code, the event structure can respond to that event.


Huh? I guess I really don't understand User Events at all then. 

========================
=== Engineer Ambiguously ===
========================
0 Kudos
Message 21 of 43
(1,733 Views)

It's very similar to a queue in that:

Enqueue Element = Generate User Event

Dequeue Element = Event Structure

 

It is different from a queue in that you can have as many Event Structures as you like, but with a queue you only want to have one Dequeue Element location.

Message 22 of 43
(1,727 Views)

Think of it this way.  We generally think of event structures responding to user interaction (e.g. a button press).  Any number of event structures can respond to that button press.  The User Event is a way to programmatically generate an event (similar to if we used a Value(Signalling) property node to simulate a button press).  Any event structure that is registered to see the event, will respond to it.  You can generate the event anywhere in the code you wish.

 

The example demonstrates this.  Two User Events are created (Count and Stop)  The For loop generates a Count event at each iteration, then a Stop event is generated when the loop is complete.  The event structure below the For loop is registered for both events. So, for each Count event, the event structure responds by  placing the value from the Count event into the Counter indicator.  Then the Stop event will, in it's event, cause the event structure to terminate.

 

user event demo.png

0 Kudos
Message 23 of 43
(1,718 Views)

@RTSLVU wrote:

Huh? I guess I really don't understand User Events at all then. 


Yes, they are horribly named.  They are actually Programmer Events.

 

Here is an example I put together once upon a time for a few presentations:


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
Download All
0 Kudos
Message 24 of 43
(1,696 Views)

@Mancho00 wrote:

Think of it this way.  We generally think of event structures responding to user interaction (e.g. a button press).  Any number of event structures can respond to that button press.  The User Event is a way to programmatically generate an event (similar to if we used a Value(Signalling) property node to simulate a button press).  Any event structure that is registered to see the event, will respond to it.  You can generate the event anywhere in the code you wish.

 

The example demonstrates this.  Two User Events are created (Count and Stop)  The For loop generates a Count event at each iteration, then a Stop event is generated when the loop is complete.  The event structure below the For loop is registered for both events. So, for each Count event, the event structure responds by  placing the value from the Count event into the Counter indicator.  Then the Stop event will, in it's event, cause the event structure to terminate.

 

 


I think I understand what you are showing, but not well enough to use that in my program.

========================
=== Engineer Ambiguously ===
========================
0 Kudos
Message 25 of 43
(1,684 Views)

As stated earlier, User Events, are like queues, or any other message you may want to send in LabVIEW, channels, notifiers, etc.

 

There are a few differences:

  1. Queues – lossless, many-to-one paradigm
  2. Notifiers - lossy, one-to-many paradigm
  3. Channels - Haven't used
  4. User Events
    1. Subscribe to multiple publishers with different data types and events
    2. Events can be dynamic and change at run time
    3. One to many and many to one paradigms are possible
    4. Debugging

So if you know how to use queues, then you know how to use User Events. The main difference is the syntax, it is like learning a new language.

 

Below are images from Jack Dunaway's talk that I borrowed/stole for a talk. I wish I could find the original slides.Snap6.jpg

 

 

Now look at the way queues are:Snap7.jpg

 

I like using User Events for messages because I can mix/match events, including DAQmx Events. I also like them because with "one wire" I can send a message anywhere in my program, I do not need an UI queue, a Data queue, etc.

 

Since you are refactoring your program, it may be worthwhile to learn how to use User Events, even if you do not end up using them.

 

mcduff

 

 

Message 26 of 43
(1,668 Views)

The summary by mcduff at the top of msg #26 is a really useful summary to keep in mind.

 

There are applications where User Events are a much better option than standard Queues, but there are other applications where it doesn't make a lot of difference.  It sounds to me like yours might be one of the latter.

 

I've got (almost) nothing bad to say about User Events, but I *would* say that there's a notably longer learning curve to get to know them well than you would face with Queues.  There's more capability and power available but as always, with great power comes great responsibility.  My advice would be to stick with techniques you know for *this* refactoring project, and then try to get to know User Events on some smaller project.  They're worth getting to know.

 

I've personally adopted a common practice of strictly hierarchical QMH message loops.  Each child loop reports back only to its one immediate parent, and each parent only sends messages down to its own immediate children.  Up at the very top is the main brain that coordinates everything.  It isn't the most efficient, but the rigid structure has proven helpful for troubleshooting and feature addition because it prevents a lot of complexity.

 

My instrument driver loops are always child loops.  They get 2 Queue refs as inputs, one for incoming messages *from* their parent, one for outgoing messages *to* their parent.  I've stuck with the standard {string, variant} cluster as the datatype for all message queues which makes it easier to make reusable utility functions (such as the scheduled messages I mentioned earlier).

 

 

-Kevin P

 

ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
Message 27 of 43
(1,655 Views)

@Kevin_Price wrote:

...


You almost exactly described the Actor Framework, just without OOP.  You might want to give it a good look.


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 28 of 43
(1,651 Views)

This probably should be moved to a different thread,but here it goes ...

 

Unlike @Kevin, I have a decentralized architecture. My messages get sent everywhere, I have a helper loop with each subloop that filters all the messages and only sends the relevant messages to the subloop. So like @Kevin,my cluster also has a string and variant payload along with a "loop address". For example, I typically have an instrument loop, data loop, UI loop, etc.  The loop address would be an enum with kinds: Instrument, UI, Data, etc.

 

I also include a debugger that logs each loop state and time, useful for debugging something that is sending messages everywhere.

 

My main reasons for using User Events:

  1. When I first looked at the QMH template, I could not understand it. It had a mix of queues, events, and notifiers. Too complicated for me, I needed something simpler.
  2. I use the JKI State machine for loops, it has an event structure built in, that is, a mailbox for User Events.
  3. This may/probably is considered bad programming practice. But, ... , since I use the JKI State machine, I may need one of my external loops to "open their front panel" from time to time so an user has access to more advanced features. The JKI state machine allows me to have an event loop for any front panel interactions along with receiving messages from other loops into the same event queue. So if someone closes the program, the message to all the loops goes to the same queue, I do not need to worry about closing loops by other means.
  4. Debugging - LabVIEW now includes an Event Inspector that you use to watch events happen in real time.
  5. Although the centralized loop structure is probably the correct way, not sure I am not a programmer, I like the chaos of a decentralized structure. I can have a "Watchdog" loop monitoring the battery status and send a "Shutdown" command to all loops with a single message if the battery percentage goes below a certain amount. I also like that I can pop up an external dialog for an error and have the user decide to try and ignore the error and continue or exit the program from the dialog window. The exit message gets sent from the dialog window and all loops can properly close without having to use the "Force LabVIEW to Exit" primitive.

mcduff

0 Kudos
Message 29 of 43
(1,625 Views)

@RTSLVU wrote:

@Yamaeda wrote:

Your Scan Interval delay shouldn't be in the Consumer, but in the producer.

/Y

I don't want the instrument to only measure once a minute if that is the data logging rate, 

I want the instrument to continue to measure at its configured update rate and save the last reading once a minute.

 


Well, with your current design you're misusing the queue as your solution to not have it grow indefinatly is to simple ditch it. I'd have the sampler collect into a buffer (shift register or AE or similar) and have the logger as a separate loop which simply grabs the last value from the buffer, no queue at all.
An alternative is that the sampler grabs 1 sec worth of samples and enqueues them and the logger grabs the last. No emptying of queue needed.

/Y

G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
0 Kudos
Message 30 of 43
(1,612 Views)