LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Dr. Damien's Development - Event Structures I - Basics

Event structures are commonly used to prevent polling when servicing a user interface. This results in less CPU time used and better performance. For example, the original NI-SCOPE Soft Front Panel was written in LabVIEW 6.0, which had no event structure. It had a polling rate of about 20Hz. It was converted to use the event structure when LabVIEW 6.1 became available. This both sped up the user interface (no delay for event handling) and reduced CPU usage by about 30%. This is the first part in a short series on using the event structure. It will cover the most common use case of servicing a GUI.

 

SimpleEventStructure.png  (code below uses local variables)


This VI shows a basic implementation of the event structure used to handle addition of two inputs, updating the output. While it works, it suffers from three issues.


  1. There is no obvious way to initialize the application (when it starts, the output is not updated).
  2. There is no good way to do the same thing based on two different events. In this case, a change of either input should result in the change of the output. Another common use case is the exit function. This could be triggered by a button, the window close button, or the operating system as it shuts down.
  3. If the event takes a significant amount of time, the UI is locked while it occurs. This can be changed with an option on the event itself, but doing so is often a race condition waiting to happen.

 

In this case, the second issue could be solved by simply using a single frame of the event structure to handle both the X and Y Value Change events. However, this is less useful when the two events are of different types. The exit case is a good example. An exit event can be triggered by the Application, VI, or a control. While you can put all these into the same event case, you end up losing a lot of information doing this. The values passed to the event structure on the left side are dependent upon the actual event. If you link the case to multiple events of different types, you get an intersection of the values, not a concatenation.


Another option for the second issue is to always put all your code into a subVI which executes in the appropriate event case. This works most of the time, but can run into issues when a lot of high–performance front panel interaction is needed. Locals outperform Value properties by about three orders of magnitude, so direct access to the front panel is often a plus. There are also maintenance issues. If you need to add inputs or outputs to the subVI, you will then need to update all locations.


To solve all these issues, use the event loop as a producer and create a queue driven task handler as a consumer. This is analogous to the proxy method of interrupt handling used by real time systems. The task handler can be configured as either synchronous (in the same loop as the event handler) or asynchronous (in a different loop). Examples of both are given below.

 

EventStructureWithSynchronousTaskHandler.png


EventStructureWithAsynchronousTaskHandler.png

 

Now that we have a task handler, it is a simple matter to preload it with the add operation to initialize the output. The task handler also makes doing the same thing from two different events quite easy (launch the same task). Finally, long tasks do not take place in the event handler, but take place in the task handler, freeing the GUI. The choice of synchronous or asynchronous depends on the application. I often end up doing both. For most things, I prefer the synchronous, but this is a personal preference.


A common problem, when using event structures, is event build–up. This usually happens when you have a quickly occurring event and a slow handling routine. For example, Mouse Move and Value Change on a slider control can produce copious quantities of events. If the task associated with these events is slower than the event, you get event build–up. You need some sort of event throttling. A couple of years ago, altenbach started a thread on this issue. I recommend you read the thread and use his elegant solution.


Next time, we will look at dynamic event registration and why you would want to do this.

Message 1 of 5
(5,871 Views)

Thanks for the Event structure basics lesson.

 

I have created a simple vi (attached) consisting of an Event structure that I am very pleased with but being inexperienced

I would like some feedback as to whether I used the proper convention or not. The intention was when called the vi pops up

running and allows the operator to setup a DC power supply via DIO bit and at the same time display output voltage and current, then simply close

and return to the caller when either continue or Exit is clicked.

 

What surprises me is how the DAQ vis are placed in the time out case.

Am I doing something that you would not advise here? Comments welcome.

 

Thanks much, 

cifer

0 Kudos
Message 2 of 5
(5,739 Views)

cifer, you have run into a typical issue that many beginners face, especially if they came from a text-based language background.  You have taken an inherently parallel process and tried to force it into a serial model.  You end up with a polling architecture using an event structure.  Try the following:

  1. Move the entire Timeout case to a separate while loop.  It is a repetitive data acquisition task that does not depend on anything in the UI portion and simply slows the UI down and forces the event structure to poll. You can stop the while loop by ORing local variables which read your exit and continue buttons  (this will necessitate using a different mechanical action on your buttons, which will require initializing them).
  2. The USB communication appears to only need to run when something changes.  It should be put into a task, as detailed above (synchronous or asynchronous handling is up to you). This will also allow better initialization code.

You also did not post any of your subVIs.  The easiest way to do this is to Save As... >> Duplicate hierarchy to new location, zip the result, and post.

A common modification to the command processor is to make the data a command/value pair, usually an enum/variant pair.  This allows you to pass information to your commands.  In your case, you probably do not need to do this, since you can get your information directly from the front panel variables.

 

Good luck.  You might want to start a different thread if you have more questions, since it looks like most of the issues you could run into are not event structure related.  You will also get faster response.

Message 3 of 5
(5,686 Views)

Thank you Dr. Gray for starting this series.

 

Ton's Nugget on Dynamic Event Registration can be found here and may help you out when you get to that Nugget.

 

Q: You screen shots make me ask "Did you take those screen shots on a Windosw 7 machine?" Those super-sized property nodes look like what is happening on my new machine.

 

Ben

 

 

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
Message 4 of 5
(5,646 Views)

Ton reminded me of his nugget right after I posted this one.  I plan to reference it and it will make my next post a lot shorter!

 

I took the screenshots on a Windows Vista machine.  Vista introduced the new, bigger fonts, which have been the bane of many a GUI developer's existence.  I dedicate a post to it during the Xylophone series, since I developed on a Vista machine here at work, but used the application on an XP machine.  Being a typical engineer, the alignment differences annoyed me enough to fix them.  Unfortunately, the fix is not trivial :(.

 

For those of you who noticed, one of the snippets also disconnected an event structure frame from its event, and does not work.  The code in the zip file does work.  

Message 5 of 5
(5,584 Views)