I have multiple VIs running in parallel. I want to instantly comunicate data from one VI to another. I am trying to accomplish this using user events. All of my VIs share a dynamic event reference through a global variable. When I issue the user event from one VI, about 80% of the time it is received correctly by the other VI. The other 20% of the time, the event is not recieved and the data is not transmitted as intended. Here is some information about the VIs that are doing the transmitting and receiving:
Transmitting VI: front panel is open, no activity happening on the panel, no computation happening. After transmitting the user event, the event loop goes to the waiting state.
Recieviing VI: front panel is closed, no activity is happening.
Is this a bad way to transmit data from one VI to another? I dislike using global variables because you need to constantly poll the variables, and you can run into race conditions, but perhaps this is what I should do. Does anyone have experience using user events to communicate data between VIs?
Solved! Go to Solution.
Global variables are evil
try using queues to communicate between parallel VIs
if you use obtain queue and give it a name then that queue can be accessed in another vi that obtains a queue with the same name
The dogma is running thick these days: Global Variables are NOT inherently evil.
If you are storing the event reference in a global variable ONCE and using it many times, that is perfectly fine.
Is that what you are doing?
You can also use a notifier: you can use a NAMED notifier where you supply a name at both ends. But you have to poll the notifier on the receiving end.
The EVENT is probably the best way to go. You should NOT be OBTAINING the event more than once.
OBTAIN the event once, and feed the refnum to both the supplier and the receiver. GENERATE an event when data is available at the supplier, REGISTER for it in your EVENT structure and RESPOND to it when fired. Kill it only when the program is done.
What you describe with events is very similar to what I have done. I create a user event once and write it to a global. Then I make a dynamic registration refnum and save to global. The main VI spawns the other VIs after writing these globals, so there is no race condition with these globals. Then these VIs use the user event and registration refnum to send and receive user events. To me this is the perfect solution: trasmit data instantly with no polling. Unfortunately I see what looks like a race condition in the guts of the event handler. Sometimes the event just does not get recieved, but sometimes it is recieved ok, so I don't think there is an error, just a timing issue. I have noticed other weird behavior: I have a button on one VI that triggers the transmission of the user event. If I press the button twice very fast, the event gets received. If I just press it once, it rarely gets received. The receive success % seems to depend on what is happening on the panel of the transmitting VI.
Have you used this method before? Is this common practice? I am not sure if I am misusing the user event feature, or if there is really something unusual about my VI.
I personaly use event structures only in the user interface vi and use queue's and notifiers for all modular VIs
Notifiers and Queues do not need to be polled
they have a timeout which is default to -1 which means wait forever
but if the queue is destroyed then the vi that is waiting for the dequeue operation will continue but with an error
One thing to keep in mind when using queues and notifiers is that if there is an error comming into the queue or notifier operation then that function will not work
I like to always include a error handler in all of my VIs that converts errors to warnings at the end of each loop iteration
Key differences between Notifiers and Queues:
you can have many subscribers to a Notifier and all subscribers will receive the notification
Notifiers do not buffer data
Queues buffer data but you cannot have multiple subscribers ( once an element is dequeued from the queue it is gone forever)
By default, an EVENT structure locks the front panel while it processes an event. I don't think that's causing what you're seeing, but be aware of it.
That's usually what you want.
I have a receiver that receives TCP data in blocks, at 10 Hz and dispatches an event on every one. In addition, every 5th one of those (2 Hz) triggers another event, which causes display of data on screen. I've never had a problem with any of that.
One rule: I do as little inside the event structure as possible.
If I press the button twice very fast, the event gets received. If I just press it once, it rarely gets received.
There's nothing inherently wrong with using events for what you describe. You'll have to post some code for me to help any further.
It's possible your two VIs are not yielding time very well. I can't tell from here.
Then I make a dynamic registration refnum and save to global.
This is most likely the source of your problem. The documentation does not stress this enough (and LV does not enforce it) but you should NEVER share event reg refnums between event structures. Each event structure has to have its own reg for events node or your events will disappear, as you've seen.
As long as you remember this basic rule, the architecture you're using should be fine, although I would generally avoid putting references in globals. You seem to have taken some percautions (top level VI opens them, makes sure to write before running the readers, only one writer), so it probably won't break for you, but still.
Anyway, as the others have mentioned, there are also other ways of passing data around between VIs.