LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

How can I communicate betwen parallel asynchronous VIs?

Howdy all,

Here's my situation:
- I have some task that needs to be executed in parallel to the currently running VI. In fact, this task needs to executed in parallel to a number of VIs,
so I've decided to build a sub-vi to handle this task.

- This task involves performing some processes every X number of milliseconds (usually in multiples of 1000). This task will be performed until it receives a stop-command (the user generates this signal - so I have no way of knowing when it will be)

- I still need to be able to handle user interaction with this main VI while the task is executing, so my task must execute asynchronously.

- I want to be able to send a termination command to my asynchronously executing task, and have it respond IMMEDIATELY (polling a global variable is unnacceptable).
-------------------------------------------------------

The only way that I am aware of running a VI asynchronously is to start it with the VI Server (either the Call by Reference Node, or the Invoke Node).

Originally I planned on using notifiers to send commands to the asynchronous VI. Notifiers would have been perfect, because I could break out of the waiting portion of the task as soon as I received the command (this isn't really possible when polling a global). Later I found out that notifiers are not supposed to work with VIs loaded with the VI Server. My notifier approach worked fine during testing, but wouldn't work when I compiled the program as an executable (which is what the end product will be, so I need a new solution).

I'm about to change my implementation to use Queues instead of notifiers, because I think I can achieve the same "Wait on Notification" functionality with a queue, except I don't think there is a restriction on using a Queue across the VI Server.

My Questions are:
Is there another way to get VIs to execute asynchronously OTHER than the VI Server?

Is there a better way to communicate between them? (I considered using a User Event control, and generating the commands using that, however I can't poll the status of the User Event without an Event structure, preventing me from terminating my task once the user generates the "end-task" request.

Does anybody else find the LabVIEW documentation to be frustratingly lacking at times?

Any help, comments, or stories of similar situations would be appreciated.
0 Kudos
Message 1 of 9
(3,803 Views)
Here is one suggestion and, yes, it uses the VI server.

I have a program (executable) that presses a stop button on another program's front panel (another executable). This is one way of getting data to another panel. I've included my little VI here. If you are running the subVI inside your main VI than you can just use the subVIs to open a reference to the panel and then press the button (don't forget to close your reference once done). The top level VI in this example I've included can press a button on any panel in an executable that was built from LabVIEW.

This came about because we had a program already built and tested that we wanted to make do an orderly shutdown from another controlling program. The Stop button on the front panel already exis
ted and performed the shutdown, so we just decided, "Why not just push the button?"

This is in LV6.1, but I've checked that it works in LV7.0 as well.

Rob
0 Kudos
Message 2 of 9
(3,803 Views)
Hi Rob,

Thanks for your suggestion. I had seen that method of changing the value of some panel's control before, but it hadn't occured to me to use in that manner. I thnk that's actually a pretty clever, and could be quite useful.

Unfortunately, this method wouldn't really work the way I want. My task is an iterative one, being run in a while loop. Between iterations of the loop, there is a set delay time. In certain situations, this can be quite substantial. I was attracted to using notifiers because of the "Wait on Notification" function. This would allow me to track the amount of time spent waiting, but I could break out of the wait period instantly when I received a command. If I used the "Wait" function and specified a certain length of t
ime, I can do nothing until that time has elapsed. So if the delay is 10 seconds, my VI won't terminate for 10 seconds. I could break the wait down into several sections to reduce the time between sending the command and receiving it, but this would amount to polling a variable and I don't want to do that.

In any case, sincere thanks for your suggestion.

Victrick
0 Kudos
Message 3 of 9
(3,803 Views)
Yes, unfortunately, event structures do not notice data changes when you use the VI server like this (only when you manually change the control - Doh). So that idea is out.

It might be possible to build a parallel loop in the subVI that does nothing except watch for the button to be pressed and can then do what's needed to shutdown the subVI. A little awkward but functional.

I take it that you don't want to use the "Abort VI" method from the Invoke nodes. That would be "instant", but just ends the VI running - no orderly shutdown (if you need that).

Well, have fun with it and let us know what you settle on for a method.

Rob
0 Kudos
Message 4 of 9
(3,803 Views)
Not sure if this will help, but here's a trick I just used.

The main loop handles UI stuff - changing which channel gets plotted, such things as that. It's a WHILE loop with an EVENT structure in it.

A separate WHILE loop needs to run every 1000 mSec. It reads DAQ data, calculates averages, and stores data away.

I set the DAQ loop to wait on an occurrence, with a 1000 mSec timeout.
Inside the DAQ loop I put a CASE structure, selected by the TIMED OUT output from WAIT ON OCCURRENCE.

If the occurrence timed out, I perform the DAQ operations, and loop.

If it did NOT time out, it must have been triggered, so I terminate the DAQ loop immediately.

Inside the UI loop, I trigger the occurrence based on a DONE button.

Outside BOTH loops, I genera
te an occurrence that feeds to both TRIGGER and WAIT functions in both loops.
You can make THAT connection thru global variables, or pass thru connectors, with no penalty.
Steve Bird
Culverson Software - Elegant software that is a pleasure to use.
Culverson.com


LinkedIn

Blog for (mostly LabVIEW) programmers: Tips And Tricks

0 Kudos
Message 5 of 9
(3,803 Views)
As long as your subVI doesn't need to keep running after the main (user interface) VI has quit, there's no need at all to use VI Server, or to meddle with control references - just drop the subVI on the diagram of the main VI, outside any loop.

To stop the subVI (and start it, if you need to control this too), a notifier should work fine. Create the notifier on the main VI's diagram and wire it in to a terminal of the subVI. You can use the Wait on Notification timeout to control your loop timing, just as you suggested. You could generalise this approach to control the subVI in sophisticated ways - changing the time interval or other aspects of the task, for example - by having it read and interpret the data you send in the notifier (or a queue).

Please tell me if
I've misunderstood and this doesn't do what you want for some reason, but it seems like it should be all you need. Incidentally, I've never heard of notifiers 'not working with VI Server' and I'm sure I've successfully passed notifiers to VI's called by reference before, but I'm afraid I don't have the code any more to check this...
0 Kudos
Message 6 of 9
(3,803 Views)
tmh,

No, I'm pretty sure you understand perfectly, as that's exactly what I wanted to do. I knew that if you had two loops on a block diagram, they would execute in parallel, but I assumed that if you had a loop and a SubVI on a block diagram, that whichever one started executing first would have to terminate first. I was making the problem much more difficult then it needs to be, as that method would allow me to use notifiers to achieve the intended effect.

As far as notifiers 'not working with the VI Server' as I must have put it, I got that straight from the LabVIEW help files. Under the topic "Notifier Operation Functions" I read that "You cannot use notifiers to communicate with VIs on other computers. For example, you cannot use notifiers to communicate across a network or the VI Server."

Originally, I was using a named notifier. So, my "master" vi would create a notifier to send commands with, then it would launch the "slave" vi asynchronously with an invoke node, and send commands when necessary. The Slave obtained the notifier by using the "Obtain Notifier" vi, supplying the same name as the Master did for the name parameter. This worked fine when I was testing - however once I built my program to be an executable, the Slave created a new notifier, rather than obtaining the same one being used by the Master. (I'm not 100% sure that's the exact reason - it may just not have received commands [it was a while ago that I was playing with that approach]. But I do know that that method works fine in an uncompiled program, but once it's compiled, it stops working. Who knows - there may exist actual ways to pass the notifier, like a global variable or something like that).

According to the *fabulous* LabVIEW documentation, Queues don't have this limitation, so I rewrote my VI to use a queue of length one, rather than the notifier.

-----------------sidebar------------------------
(does anyone find that the LabVIEW documentation can be frustratingly lacking at times? Like, why can't I use notifiers across the VI server? And why can I use queues? I'm not asking for them to show me the guts of LabVIEW, I just think that it would give developpers more control and confidence when coding that they know what's going on, and have at least a general idea of how things work)
--------------end of sidebar--------------------

However, somewhere in my switch between Queues and Notifiers, I must have messed up something, as after that worked fine during the testing phase, after a compilation, I received an error (1013 I believe) whenever I tried to load my slave saying "Front Panel Heap Dump" - which is strange because the front panel of my slave should not have been loading, and was supposed to have been removed from the executable.

Not that that last bit is super relevent to the original topic of discussion, but it might be useful to someone later on.

In any event, thank you for your help. I suspect that that will be the perfect solution for my needs, and when I get back to that chunk I was working on and get it working, I'll let you know.

Thanks again.
0 Kudos
Message 7 of 9
(3,803 Views)
and I guess I should come up with a new expression other than "frustratingly lacking at times", since I used that one already...
0 Kudos
Message 8 of 9
(3,803 Views)
Yup, I've reworked my VIs and it works exactly as I wanted. I feel pretty dumb... my new golden rule: keep it simple stupid.

thanks again
0 Kudos
Message 9 of 9
(3,803 Views)