03-06-2018 12:32 PM - edited 03-06-2018 12:33 PM
@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.
03-06-2018 12:46 PM
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.
03-06-2018 01:20 PM - edited 03-06-2018 01:42 PM
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.
03-06-2018 02:00 PM - edited 03-06-2018 02:01 PM
@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:
03-06-2018 02:45 PM
@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.
03-06-2018 05:42 PM
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:
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.
Now look at the way queues are:
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
03-06-2018 06:55 PM
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
03-06-2018 07:12 PM
@Kevin_Price wrote:
...
You almost exactly described the Actor Framework, just without OOP. You might want to give it a good look.
03-07-2018 07:59 AM
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:
mcduff
03-07-2018 09:26 AM
@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