LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Notifier between VIs not working

Solved!
Go to solution

I've been reading the topics about issues with notifiers, and I've tried different solutions, without success, so I'd like to ask for someone to help.

 

I'm working in a configuration screen for a data acquisition application. The VI has two areas, one with generic parameters as individual controls (for example, the filter used for all channels) and a sub-VI loaded within it with parameters for individual channels. Some interaction happens between the two areas so that, for example, if the "manual config" switch button for a specific channels is turned on, its filter parameter altered, and then the switch is turned off, the sub-VI changes the filter value back to the generic value; and inversely, if the generic value is changed, this change is reflected in all the "filter" control for all the channels in which the "manual config" switch is turned off.

 

This design has 3 loops running in parallel: one listening for events in the main VI's controls and writing stuff in the sub-VI when something relevant happens; another listening for events in the sub-VI's controls, and copying things from the main VI one when something relevant happens; and a third listening for other stuff (this one is still a skeleton).

 

I'd like things to work in such a way that if an error happens in any of the three loops, or if the "cancel" os "save" buttons are pressed (the 3rd loop is listening to those), the three loops end and then serial processing continue. So I configured a named boolean notifier that can be enabled by any the three loops and stops all three. However, it isn't working. When I send the notification in one of the loops, for example by inducing an error in one of them, the other loops don't receive it, and as a result the application hangs.

 

I've tried the Wait on Notification with and without Notifier History; adding and removing the Release Notifier; creating the notifier before the sub-VI is loaded and setting the Obtain Notifier's "create if not found (T)" input to false on the two sub-VIs; but without luck.

 

Can someone please enlighten me as to what I'm doing wrong

 

Here are the captured screens:

 

Main VI's loop.Main VI's loop.

 

The sub-VI that loads the two VIs with their own loops..The sub-VI that loads the two VIs with their own loops..

The 2nd loop (No Error view)The 2nd loop (No Error view) The 2nd loop (Error view)The 2nd loop (Error view)

 The 3rd loop (No Error view)The 3rd loop (No Error view)

 The 3rd loop (Error view)The 3rd loop (Error view)

Thanks in advance!

 

PS.: I attached a file below and I don't see an option to remove it. It's the same as the second one above. Please ignore it.

0 Kudos
Message 1 of 12
(5,254 Views)

Hi Alex,

 

The resolution of the first image is very low, so I cannot see your "main loop".

 

Whenever you obtain a new reference to a notifier you must later release it. It will completely destroy the notifier unless it is the last reference open. 

 

You have an event structure already in 2 of your 3 VIs, maybe it would be easier to use a User Event rather than a notifier with a timeout.

Message 2 of 12
(5,239 Views)

You have Event Structures inside the "modules". So just get rid of the Notifiers, and use Dynamic User Events to broadcast commands/info to all those modules which registered for the particular event. This can be a command to stop the loops, even including error info.

Here behind this link there is an example how to use User Events for intercommunications between parallel running modules (the actual topic is not relevant, about Channels, so only check the User Event part). As you see, both the main VI, and the parallel running subVI are registered for the "command_data" Event. It means, if you fire this Event from anywhere in your app, all registered Event Structures will react in a lossless way. Notifiers are lossy, do not forget!

 

https://forums.ni.com/t5/LabVIEW-Idea-Exchange/New-Message-Channel-wire-type-with-option-to-specify-...

 

 

Message 3 of 12
(5,233 Views)
The resolution of the first image is very low, so I cannot see your "main loop".

Here's a zoomed-in version. It's very simple right now, just a skeleton for future functionality:

 

Main loop zoomed in.Main loop zoomed in.

Whenever you obtain a new reference to a notifier you must later release it. It will completely destroy the notifier unless it is the last reference open.

Understood, I will do so. The Release Notifier icons should be there, I had removed them as part of my testing yesterday and forgot to put them back.

 

The problem however is that none of the loops ever end after I send the notification from one of them. It's as if the notification hasn't been broadcast. Or, conversely, hasn't been received.

 

To sum it up:

 

  1. The three loops are similar to the above snippet.
  2. They all have a "Obtain Notifier" that enters into a loop, named "CS_stop".
  3. Within the loop, they are read by a "Wait on Notification" set to 0 ms.
  4. The three loops have a 50ms timeout, so the "Wait on Notification" is read up to 20 times per second.
  5. Under specific conditions, any of three loops can set the notifier boolean to True, ending itself and (presumably) the other two loops too.
  6. And after the three loops end, there's a "Release Notifier" for each (not shown in my previous code captures).

 

Something I must be doing wrong, as it seems it should be be pretty straightforward.

 

You have an event structure already in 2 of your 3 VIs, maybe it would be easier to use a User Event rather than a notifier with a timeout.

I don't know User Events, it seems interesting. Can the same User Event be triggered from any of the three loops and affect the three?

 

Thanks!

0 Kudos
Message 4 of 12
(5,225 Views)

I don't know User Events, it seems interesting. Can the same User Event be triggered from any of the three loops and affect the three?

 

Yes. Did you read my post? For important messages, never use Notifiers. Use Queues, User Events or Channels (Messenger or Stream types)...

0 Kudos
Message 5 of 12
(5,218 Views)

As you see, both the main VI, and the parallel running subVI are registered for the "command_data" Event. It means, if you fire this Event from anywhere in your app, all registered Event Structures will react in a lossless way. Notifiers are lossy, do not forget!

Thanks! I'll look into it and most probably do it!

 

However, I'd still like to understand Notifiers better. I've tried the "Wait on Notification with Notifier History" instead of the simpler "Wait on Notification" so as to try and avoid the lossy aspect of notifiers, but it also didn't work. this suggests something is incorrect on my usage of them, and I'd like to know what it is so that I can use notifiers properly in future.

0 Kudos
Message 6 of 12
(5,216 Views)
Yes. Did you read my post? For important messages, never use Notifiers. Use Queues, User Events or Channels (Messenger or Stream types)...

Sorry, you had replied while I was typing. I'll look into it. Thanks!

0 Kudos
Message 7 of 12
(5,214 Views)

Hi Alex, User Events are great for one to many communication, as you want to do. 

 

I haven't looked into the notifier with history either, but I don't think it has anything to do with the lossy aspect, I think it just adds some time stamping capability. Either way, the only possible notification is a True being sent, so you shouldn't care about losing anything.

Message 8 of 12
(5,205 Views)
Solution
Accepted by topic author alexgieg

I changed my VIs to User Events. And they didn't work either. The behavior was the same. So I began messing around and discovered what the issue was. It turns out that "Generate User Event" (and probably "Send Notification" too, but I haven't tested) doesn't generate the event if its error input receives the error you're trying to generate an event about. End result: unwiring the error input from the icon, and using a Merge Errors afterwards, did the trick.

 

This was a quite silly bug, but I liked learning about User Events, and I will start using them way more than before. Thanks for your suggestions then! They both provided me new knowledge, and pointed me in the right direction!

0 Kudos
Message 9 of 12
(5,176 Views)

Of course you have a glaring race condition on your toplevel.

 

Your controls (B) will get read immediately as the outer case structure starts and we don't know if the locals (A) are written before or after that happens. Classic race condition! More importantly, if you change any of these controls while the inner while loop is spinning, their new value will not get read again by the code until the next time this VI executes. Most likely the code will operate on stale values most of the time.

 

Even if you think it does not matter here, I would fix that to avoid surprises in the future.

 

RaceCondition.png

Message 10 of 12
(5,174 Views)