LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Dr. Damien's Development - Event Structures III - Communicating With User Events

Event Structures III?!? What happened to “Event Structures II — Dynamic Event Registration?” As mentioned by Ben in the last installment I wrote, a community nugget was written on that exact subject by TCPlomp almost three years ago. It covers the subject quite well, so on to part III, using events for communication.

 

User events are an excellent method of broadcasting information. While they can be used for any variant of one/many » one/many communication, they are probably best for one » many and many » many communication. Take a moment to download the attached code (LabVIEW 8.2.1), unzip to the directory of your choice and run MultiInstanceVI.vit. By clicking Launch Another, you can launch multiple copies of the VIT (VI template). The other buttons serve to stop either a single VI or all of them. Typing into message causes all instances to update their message. Play with it awhile and you will notice a “problem” in the implementation, which I will explain below.

 

User events are created using Create User Event primitive. This can be found in the Dialog & User Interface » Events palette. Once created, they must be registered using the Register For Events node. The output of this node must be connected to the dynamic event terminal input of an event structure. By default, these terminals are not shown. Right–click the border of the event structure and select Show Dynamic Event Terminals to make them visible. Once you have connected the Register For Events node to the event structure, the events you have registered can be added to the events handled by the event structure. The output data of the event is the data type of the user event.

 

Fire a user event using Generate User Event. This requires both a user event reference and the data to send. When your event structure exits, unregister all events using Unregister For Events. Close your user events using Destroy User Event. This example does not do that for the same reason it has an implementation issue — to avoid making the example too complex. Note that the event terminals of the event structure can be wired inside the event structure as well as outside. This is useful for advanced applications where you want to dynamically change which events are registered and not registered. See TCPlomp’s nugget referenced above for some examples of this.

 

User events are not named. This means you must pass references around to use them. In this example, a simple functional global is used to create and cache the user events. The functional global’s first call must be from the original VIT, or subsequent use will not return the proper path to the root VIT. In addition, if you close the original VIT before you close all the other instances, the user events will cease to work. This is because the user events were created by the original instance of the VIT. When that instance stops, LabVIEW cleans up all references still open. This causes the use of these references to fail (error 1, invalid input). When using user events (or any references), it is important to keep this in mind.

 

User events can have arbitrary data type, so can be used to pass almost any type of data around. For example, the broadcastStopAll event is a simple boolean. There is no reason it could not also include such information as where it came from, its urgency, or filtering parameters. This makes it very powerful.

 

On the down side, as mentioned before, user events are not named. If you need named behavior, you should use notifiers, which also accept arbitrary data types. However, notifiers are lossy (user events are not). Subsequent commands overwrite previous commands, so it is easy to get into race conditions. I would expect notifiers to have better performance than user events, but I have not benchmarked this. Why? User events go through the event structure, which usually means a trip through the UI thread. Once again, I have not checked this, so there may be conditions (i.e. event structure with only user events) which do not have this issue.

 

Please let me know if you have any comments or questions.

 

Previous Installments

  1. Event Structures I — Basics
  2. Event Structures II — Dynamic Event Registration (by TCPlomp)

 

Attached code is in LabVIEW 8.2.1.

Message 1 of 5
(4,340 Views)

Used user events for some time for Communication with DLL's. I found it as the only way to keep a DLL running and transmit messages to running VI's, through queues.  An example that I posted is:

http://decibel.ni.com/content/docs/DOC-11373

sure exists anothers in example codes

cosmin 

0 Kudos
Message 2 of 5
(4,258 Views)

I like using User Events in my code.

 

It DOES have some speed disadvantages versus Queues and Notifiers (discussed elsewhere before but I can't find it) but I find for UI work, the flexibility of having a strictly typed messaging system (As opposed to variants or Strings via Queue of Notifier) a lot easier to debug.  Of course LVOOP mixes things up here, but for smaller code snippets, I find a LVOOP messaging system still a bit too much.

 

--shameless plug--

I would of course like to see ALL LV Events display the same behaviour as User Events (Registering, unregistering, swapping at run-time etc) along with other changes... but my ideas on improving the state of events within LabVIEW on the Idea exchange (here, here, here, here, here and here) seem to be gaining little support.

--shameless plug--

 

Shane.

0 Kudos
Message 3 of 5
(4,234 Views)

I make extensive (re)use of User Events for communication between the modules in my Apps. The concept is published in this community nugget by me.

 

Felix 

Message 4 of 5
(4,215 Views)

 


DFGray wrote:

 

User events go through the event structure, which usually means a trip through the UI thread. Once again, I have not checked this, so there may be conditions (i.e. event structure with only user events) which do not have this issue.


 

The following is my understanding:

 

=======

 

 

It's important to note that neither the event structure itself nor dynamic events cause a switch to the User Interface Thread.  Functions inside the event structure (e.g. property nodes, invoke nodes) can cause a switch to the UI Thread when they operate on UI components.

 

In this discussion, Jason King points out that:

 

"There is nothing specific about the event structure that requires the event-handling case to run in the UI thread.  In fact, there is not any event that will force it to run in the UI thread"

 

"Reading from or writing to a front panel terminal or local variable does not cause the diagram to run in the UI thread."

 

"Any actual processing of user interaction, however - either looking at user interaction to determine which events to generate or finishing processing a filter event after the event structure has had a chance to discard it or modify any of the event details - requires the UI thread."

 

"Pretty much anything you do with the reference to a control or indicator will cause a switch to the UI thread (property nodes, invoke nodes, etc)"

 

=======

 

That said, maybe you could correct me if, as you mentioned as a possibility, you find that code switches to the UI Thread when an Event Structure is handling non-UI events when it's also registered for UI events.


Certified LabVIEW Architect
TestScript: Free Python/LabVIEW Connector

One global to rule them all,
One double-click to find them,
One interface to bring them all
and in the panel bind them.
Message 5 of 5
(4,083 Views)