LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Communication with an asynchronous called VI

Hi,

 

i am working on an application which requires grabbing images from a video device. To do so i've chosen to go with a 'main' VI and a 'video' VI. In the main VI a while-loop and an event structure handle user inputs. The video VI uses a (infinite) while loop to get the video data. The video VI is started with an asynchronous-call VI.

Now I need the two VIs to communicate efficiently. Example:

The main-VI sends the command 'initialize'. Then it has to wait for the video VI to finish executing the request.

Then the main-VI can send 'start grab' and the video VI starts grabbing.

 

To send a command in one direction i could use a queue or a notifier. But i need to wait for some processes to finish before i can go on. A C-like function call is what i have in mind.

 

Has anyone an idea on how to implement this?

 

regards

Marvin

0 Kudos
Message 1 of 15
(5,414 Views)

Marvin,

 

that question is essentially the basics for the LV Advanced Architectures class.

 

Plenty of options:

Queue

Notifier

FGV

DVR

User Event

TCP based communication protocol

VI Server

...

 

Norbert

Norbert
----------------------------------------------------------------------------------------------------
CEO: What exactly is stopping us from doing this?
Expert: Geometry
Marketing Manager: Just ignore it.
Message 2 of 15
(5,388 Views)

We do it with Queues.  This is essentially a Producer/Consumer Design, but with the two parts running asynchronously in different VIs.  You can Queue 20 commands all at once, but they will be execute at the (maximum) rate that the Consumer can pull a command off the Queue, execute it, and come back to dequeue the next command.  The idea is that the Queue "buffers" requests, allowing to Producer to request commands at one rate and the Consumer to execute them at a different (and potentially fluctuating) rate.

 

Bob Schor

0 Kudos
Message 3 of 15
(5,360 Views)

Hi,

 

that is exactly what i have in mind. Problem is though that i need to get a return value. Let my describe an example situation:

The main app puts the "initialize video grabber" command on the queue. The videograbber VI dequeues the command und execute the necessary code. Depending on the operation was sucessfull or not, it has to send a return value e.g. "init sucessfull" or "init not sucessfull: camera not found".

Should i use another queue to send the return values back to the caller? How can the caller match responses to the corresponding command calls?

Is there an easy way to do this. I think there has to be a simple solution, because this seems to be an every day problem, right?

0 Kudos
Message 4 of 15
(5,224 Views)

@nollMarvin wrote:

Should i use another queue to send the return values back to the caller? How can the caller match responses to the corresponding command calls?

Is there an easy way to do this. I think there has to be a simple solution, because this seems to be an every day problem, right?


Yes, you should use another queue.  There are many ways to do this, depending on your requirements.

 

1. You pass in the queue reference when you initially call the VI

2. You store the queue reference in an Action Engine

3. You send the queue reference with your command (as part of the queue data)


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
Message 5 of 15
(5,211 Views)

4. You use named queues…

Best regards,
GerdW


using LV2016/2019/2021 on Win10/11+cRIO, TestStand2016/2019
Message 6 of 15
(5,200 Views)

And use the "cluster with enum and variant" format if several data types have to be send by a queue.

See here, here or here for more details.

0 Kudos
Message 7 of 15
(5,161 Views)

@nollMarvin wrote:

To send a command in one direction i could use a queue or a notifier. But i need to wait for some processes to finish before i can go on. A C-like function call is what i have in mind.

 


A function-call-like feature can be achived with a temporary Queue; create a Queue, attach it to the request message, wait for the first message received on the Queue, then destroy the Queue.  Queues can be created and destroyed quite quickly, and all these steps can be contained in a single reusable subVI.  I use my version of such a subVI at about 3:48 in this video on YouTube.  Internally, the "Query" subVI used is creating a temporary Queue to get the reply to the request.

Message 8 of 15
(5,139 Views)

Sorry to resurrect this thread, but I've been searching for half a day for a "next step" for the OP's problem. His original question was how to communicate asynchronously with a VI that has been called via Start Asynchronous Call. The proposed answers (queues, etc) are the usual suspects for async communication. But I cannot figure out (nor have I been able to find any examples of) how to communicate with a VI that has been called via Start Asynchronous Call.

 

So I expect the answer is "you can't" and the proposed solutions are instead-of's, i.e. use queues, etc instead of Start Asynchronous Call. If this is the case, how would I do the following:

 

1) Start a VI asynchronously (with inputs) based on either a timer or on user command from the GUI; there will only ever be one instance of the target VI running, I just need it to run it asynchronously with a timer VI i've written.

2) Asynchronously send commands to change its behavior (pause, resume, change parameters to sub-VIs, etc),

3) Asynchronously send a "stop" command to stop and close it.

 

I originally had the timer and the target VI combined in a single VI (attached - timer is on lower left, target VI is the large loop in the middle) which worked well, but I was starting to see main loop iteration times increase after 5 or 10 minutes of run time (we have to run for about 30 min). So I decided to re-architect the code so it runs for about 5 minutes at a time with breaks in between (which happens to match our use case).

0 Kudos
Message 9 of 15
(3,672 Views)

Consider two VIs -- Main and Video.  Main "runs the show", while "Video" runs as an Asynchronous VI using Start Asynchronous Call, and two-way communication between Main and Video is desired.

 

The simplest way to do this is to create two Queues, one from Main to Video and the other from Video to Main.  I recommend that you make them "Message Queues", where the Queue Element is a Cluster (TypeDef'ed as "Message" consisting of a "State" (I use an Enum, you can also use a String) and "Data", a Variant (so you can send a "Message with arbitrary Data").  Create both of these in Main, and pass them as either separate Inputs in the Start Asynchronous Call to Video or bundled into an Array or (my preference) a Cluster.  

 

Note that, in principle, you do not need to create Queues on Main and pass them to Video -- you could create named Queues on both Main and Video and depend on them to "link up", but since Main always runs first, I find the simplicity of a definite "creation point" and a "wired" passing of the Queue to Video preferable.

 

I'm getting eye-strain trying to view your "picture of code".  If you want some of us (I'm thinking of myself, really) to look at your code, please attach the VI.

 

Bob Schor

Message 10 of 15
(3,660 Views)