From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

How do I use a static reference to keep a VI in memory but then call it in parallel?

Solved!
Go to solution

Hello all,

 

I have a MainVI and I want to call from it a SubVI in parallel so that I can have both windows open and responsive at the same time.  The SubVI may be closed and reopened any number of times, but only one in existance at a time.  I know how to do this using Open VI Reference, providing a relative path to my SubVI, checking its state to see if its already running, and if so bring the window to the front (using Front Panel: Open method with True/Standard inputs), and if not run it using the Invoke:Run method (and optionally opening its front panel programmatically).  This method was working fine.

 

Now I have added functional global variables in my SubVI, and I want to keep them in memory inbetween opening the SubVI window.  I can do this by putting a copy of the functional global in my MainVI, even though I don't use it there for anything.  This works fine.

 

By accident, I have come across a reference to a Static VI Reference, which sounded like a vast improvement to my methodology, for the following reasons:

1) Keeps SubVI in memory all the time, eliminating the need to put the functional global in MainVI when it is not used there.

2) Tells LabVIEW to include SubVI when I build my executable, rather than me having to specifically mark it as Always Include in the build specification.

3) Eliminates the need to keep the path and SubVI name updated in a string constant in my code, in order to use the Open VI Reference.

 

However, trying to implement this solution, I have run into the problem that once you put a strictly-typed static VI reference (strict typing is required to keep it in memory) onto the block diagram, that VI is reserved for execution.  That means I cannot run it using the Invoke:Run method.  I haven't tried just putting it on the diagram directly as a subVI because I need it to run in parallel to the MainVI.  I have searched through these forums extensively, and although there are several references to a static VI reference, none of them say explicitly how to actually run the darn thing!  😛

 

I very much appreciate any insight into my problem.  If I have to go back to the old way it will work fine, but I really like the seeming elegance of this solution.  I hope that it is technically feasible and I'm not misunderstanding something.

 

Thank you for your help,

 

-Joe

0 Kudos
Message 1 of 17
(5,539 Views)

Joe,

 

i am not sure why you are working with VI references at all. The first two sentences of your post:


jmorris wrote:
[...]I have a MainVI and I want to call from it a SubVI in parallel so that I can have both windows open and responsive at the same time.  The SubVI may be closed and reopened any number of times, but only one in existance at a time.[...]

tell me that a static SubVI will do everything you want.....

Maybe you could post a small example of your current approach in order to give a better understanding if i am correct with my assumption.

 

Norbert

 

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

Okay, here's a copy of my current setup in general terms.  I tried to create Snippets with the Code Capture Tool, but since this is my first time using it I'm not sure if I succeeded.  

 

MainVI:

MainVI.png     MainVI_2.png

SubVI: 

SubVI.png

 

In creating this example, I figured out that if I keep the reference open rather than creating it each time the "Launch SubVI" button is pushed, I solve the "keep functional globals in memory" issue I described in my first post.  I am still curious about how static VI references or static subVIs could be used in order to address the other two points, and appreciate any insights you have on that.

 

When you said use static subVIs, it occurred to me that I could run the SubVI in parallel with the MainVI at startup, and have some sort of dynamic control or signal to tell the SubVI to open its front panel and basically start executing the code, and maybe link the Close button on the SubVI to hiding the window instead of actually stopping the code... that just seems like a very convoluted solution, though.  😛

 

Thanks,

-Joe

0 Kudos
Message 3 of 17
(5,488 Views)

jmorris wrote:
[...]

When you said use static subVIs, it occurred to me that I could run the SubVI in parallel with the MainVI at startup, and have some sort of dynamic control or signal to tell the SubVI to open its front panel and basically start executing the code, and maybe link the Close button on the SubVI to hiding the window instead of actually stopping the code... that just seems like a very convoluted solution, though.  😛

 

Thanks,

-Joe


Basically, this is what it's about. You can use Queues or Notifiers to "inform" the subvi. I think a "repetitive" call to the subvi in an independant running loop would be sufficient. Please note that the functional global (FGV) will not be unloaded unless the last caller is unloaded from memory. So if you Main calls the FGV as well, you don't need to worry about the FGV to get unloaded unintentionally.....

 

 

Norbert

Norbert
----------------------------------------------------------------------------------------------------
CEO: What exactly is stopping us from doing this?
Expert: Geometry
Marketing Manager: Just ignore it.
0 Kudos
Message 4 of 17
(5,477 Views)

Okay, thanks for the assistance Norbert, but I'm going to stick with my currently implemented solution, mainly because it is already implemented.  😉  Rewriting my subVI to watch for a queue or notifier and behave differently is not worth the benefit of not hard-coding the path to the subVI, and putting it in the build configuration as always included.

 

Another reason is that I do not currently call the FGV in my main VI, so I would need to add that as well in your described solution.

 

I am still interested in how anyone ever uses static VI references, just out of curiousity, if anyone knows the answer.  But in the meantime I will go forward with the dynamic VI solution.

 

-Joe

Message Edited by jmorris on 05-20-2010 09:17 AM
0 Kudos
Message 5 of 17
(5,466 Views)

Static VI references are fine.

 

To run VIs in parallel (we call it "spawning a cloned process" although that mixes some metaphors) you need to make the VI itself re-entrant. Usually "share clones" is the memory setting you want.

 

To actually launch the process you need to open it with "options" set to "prepare for re-entrant run". See diagram below.

 

spawn.png

 

The "re-entrant refnum" can be a static VI reference. I encourage this because it removes all kinds of problems that can otherwise occur when you build your application into an .exe. 

 

 

 

 

Message 6 of 17
(5,448 Views)

Thank you, Rob, for illustrating where static VI references may be useful.  If I understand you correctly, they can only really be used for re-entrant VIs. 

 

If I wanted to go this route for my situation, my understanding is that even though my subVI would be re-entrant, my FGVs would not.  Therefore everything would still work correctly (in terms of keeping variables in memory) as long as I only have one version of SubVI open at a time.  I'm not sure whether given this situation, I should choose "share clones" or "preallocate clone for each instance", or whether it doesn't matter since there will only ever be two total instances in memory (one for the static VI ref, and one that will be actually opened and run), and only one of them will ever be run.

 

In order to fully implement my setup, I also need to be able to bring the window of SubVI to the front if the button is pushed again while SubVI is open.  I think I could accomplish this by storing the returned reference to the clone that I open programmatically (setting auto-dispose reference to false), and checking that particular reference's execution state.

 

[pause to implement code]

 

Okay, I tried it, and got the code shown below.  However, this did not work for me - when I tried to launch SubVI, I got the "reserved for execution" instance that was not actually running (with the outlined grayed out Run arrow in the toolbar).  This despite the fact that probing the wires showed that the refnum I was opening was different than the static refnum, and no errors were occurring.  I set SubVI to re-entrant, and even tried both clone options (share or preallocate), and confirmed this by probing the property wire.  Any idea why it isn't working?

 

MainVI_StaticRef

 

Thanks again,

 

-Joe

0 Kudos
Message 7 of 17
(5,438 Views)

If I understand you correctly, they can only really be used for re-entrant VIs. 

 

No, a static VI reference can be used anywhere a regular VI reference (property nodes etc.) The reason for the hoop-jumping above is that we are really opening a reference to a CLONE (copy) of the VI identified by the static VI reference.

 

Okay, I tried it, and got the code shown below... Any idea why it isn't working?

 

The VI you want to clone can't be on the diagram as a "normal" subVI. When you run your application you should be able to open that VI and see it just sitting there with a run arrow waiting to run. See attached example (LV2009SP1).

 

"share clones" vs "preallocate" has to do with whether you want each clone to preserve state (such as in an uninitialized shift register). Generally you use share clones. Occasionally it is useful to have multiple copies on a diagram that each remember some data, like "timestamp of last execution" in a shift register.

 

Other VIs in your spawned process don't have to be re-entrant unless they are functions that "wait forever". All the built-in G functions are re-entrant. It's pretty common to use a queue to feed data to a spawned process.

 

Spawning a process is more difficult than just running two parallel loops. It's useful because once you've made 1 copy, you can make 50. If you just want to do two things (vs n things) at once, I would just use two loops.

  

0 Kudos
Message 8 of 17
(5,423 Views)

I actually meant it seems like static VI refs can only be used to *run* re-entrant VIs.  I know they can be used for property nodes, etc, although I don't know what good it would do to affect non-reentrant VIs if they cannot be run in the program since there is a static VI reference to them in the program.  😉

 

From my experimenting, when you say "the VI you watn to clone can't be on the diagram as a "normal" subVI", that includes having a static VI reference to it.  Since the original question was how to use static VI references to run a subVI, I'm now confused.

 

I'll definitely keep in mind next time to design parallel windows like this to run from the start in a parallel loop, since I need only one instance of each one.  However, I'm still curious as to how to use a static VI reference effectively.

 

Thanks for your patience and assistance!

 

-Joe

0 Kudos
Message 9 of 17
(5,402 Views)

Hi Joe,

 

Perhaps we could attack this from a different angle. Would it work for your application to simply hide the subVI front panel when the user tries to close the window? Then you could just reopen the front panel when the user again launched the subVI. The image below shows how you would prevent the subVI from being closed. This would also keep this VI in memory.

 

subvi_event_structure.png

 

Would this be an option for your application?

 

Regards,

Tanya Visser
National Instruments
LabVIEW Group Manager
0 Kudos
Message 10 of 17
(5,355 Views)