03-22-2010 09:10 AM
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.
(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.
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.
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.
03-23-2010 04:39 PM
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
03-24-2010 07:40 AM
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:
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.
03-24-2010 01:02 PM
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
03-25-2010 08:33 AM
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.