03-09-2018 09:26 AM
I have a Main.vi that generates user events which are received by 2 Asynchronous (x80 called) SubVi's. However, I need to eliminate a race condition when I'm saving my data.
What is the best way to make sure that my SubVi's have finished their tasks (saving their data to a common folder) before my Main.vi zips the data and archives it to a database?
My gut solution is to have an FGV/Action engine passed between the VI's that will act as a busy flag, but I don't know if there is a better way.
03-09-2018 10:29 AM
Do the asynch subVI's finish executing when they're done? If so you can use the "Prepare to call and collect" then have Main wait on them to return data.
If they're constantly running, I'd use a queue to send messages back from the subVI's to the Main VI. With Main generating user events, you can add a temporary return queue refnum that Main generates then sends to the subVI as part of the user event data it sends (or as a new user event). When it's done, it sends a message to the return queue that tells Main that it's finished, then Main can release the temporary queue reference.
You can use an FGV but I tend to not like that style of communicating between async loops; it's easy to add race conditions and it's a little harder to scale, plus it means Main has to poll the FGV instead of allowing Main to wait on queue data to come in.
03-09-2018 11:39 AM - edited 03-09-2018 11:42 AM
Since you are using User Events, I will assume that you are sending User Events to your asynchronous subVIs.
mcduff
03-09-2018 02:50 PM
Sounds "needlessly complex" to me (but then I don't really know nor understand the requirements of the task). Are the Asynchronous VIs basically a way of "spawning" parallel processing VIs without having a "bare VI" icon on the Main desktop (I'm ignoring, for now, the notion that you might want Main to do "15 steps, then spawn the sub-VI as a parallel process)?
I've been using a QMH-like design for my Main and for my Parallel Loops. Since a Message Handler basically "waits for a Message", Main can "start" Parallel Loop 1 by send it Loop 1's "Initialize" Message.
As a result of this simplified Design choice, the code is pretty easy to explain to my colleages (I just gave a 4.5 hour presentation on it, and some of the "tricks" and "What NI Forgot to Put In" that I used ...).
Bob Schor
03-09-2018 04:20 PM
@Bob Schor
Here are some potential use cases, that I actually use.
mcduff
03-09-2018 09:34 PM
@mcduff wrote:
@BOB Schor
Here are some potential use cases, that I actually use.
- I launch an asynchronous dialog box that the user can respond to. I do not want the dialog to hold up the program unless I need it to, for example, maybe the dialog is only informational and not important. I launch the VI asynchronously and I can have it listen in to Main VI via User Events, and yes, the same thing can be done with queues, maybe even Channel wires. I can also relay information back to the Main VI with the User Event.
mcduff
Ah, yes, Channel Wires (my #1 favorite new feature in LabVIEW). You cannot (ordinarily) pass a Channel Wire into a Start Asynchronous Call. I have a routine that has multiple (up to 24) identical Asynchronous Clones, and (almost) everywhere I use Channel Wires, predominantly Messenger Channels to create a Channel version of the Queued Message Handler (I call it the CMH). The only place I use a Queue is as the means to "fake" a Channel input (and output) between the Main (Top-level) VI and the multiple Asynchronous Clones. The Main can use the Queue to "fake" a Channel Input to the Clone's CMH, and the Clones can use a Queue to send (Channel) Messages back to the Main.
Bob Schor