LabVIEW Idea Exchange

cancel
Showing results for 
Search instead for 
Did you mean: 
0 Kudos
wiebe@CARYA

Allow dynamically running of an already running VI

Status: Declined

Any idea that has not received any kudos within a year after posting will be automatically declined.

I've always wondered why this is not possible.

 

So you can dynamically start a VI. Except when it's not already "running". I quoted running, but the VI itself is not running, it's just on the diagram of a running VI.

 

To start a VI dynamically, when already "running" we need to make it re-entrant. This is very limiting (see use case in following post).

 

Technically, there should not be a problem. You can create a new VI, put the sub VI on the diagram and run it.

 

Why can't we do this by reference???

16 Comments
wiebe@CARYA
Knight of NI

So here's a use case:

 

My application is done. Now the customer (and I) want to automatically test it.

 

So my application uses VI's to send events. With this events I can control a lot of what is happening. How nice would it be if my automated test framework could just dynamically call these events?

 

Unfortunately, I have to wrap each VI inside another VI, so I can call that VI. How silly is that?

 

For these event VI's, I could make them all re-entrant. But what about reading a functional global?

 

BTW. I understand the VI will only run once (e.g. not parallel), just like running the VI in a new VI.

wiebe@CARYA
Knight of NI

As for an implementation idea:

 

Dynamically Run An Already Running VI.png

Maybe give Call By Reference an option to be backward compatible?

AristosQueue (NI)
NI Employee (retired)

The diagram you just posted with the Call By Reference node works just fine when I try it. And it does wait until the subVI is finished running. I don't see the problem.

I don't have LV 2013 easily at hand to test. Maybe it used to not work? Have you considered upgrading?

 Untitled.png

 

wiebe@CARYA
Knight of NI

Stephen,

 

Well, I'll be damned. I'll have to go back to my code "in the wild" and see why I got errors.

 

The code I've posted does work in 2013 as well. I probably mixed up some techniques (run method and call by reference), but I'll do some testing to be sure.

 

What probably happened is that Call By Reference does seem to work, but it's very inconvenient since the strict type needs to be known. I'm sure I tried it, but probably it failed for another reason.

 

Any change to run an already running VI can work without knowing the strict type?

wiebe@CARYA
Knight of NI

Stephen,

 

It seems I was blinded by frustration.

 

The Call By Reference doesn't solve my issue (should have posted it as an example, it is in fact more a counter-example). You still need to pre-define everything for each VI you want to call (== a lot of extra work). It's not much better than making wrapper VI's just to run the real VI's unless all the interfaces are the same. So for my use case, I still need to make a VI wrapper so all the inputs and outputs can be read\written. It's exactly the same, only more complicated!

 

Sorry for the confusion. BUT..Dynamically Run An Already Running VI 2.png

(obviously Ctrl Val.Set also doesn't have the desired effect).

 

Can there be a way to call an already running VI dynamically AND set\get it's control values dynamically (by name)?

Intaris
Proven Zealot

So if I understand correctly, setting the Control values via VI Server works, but when you try to run it, it's already reserved and fails.

 

Hmm. Are the controls you are trying to set also on the connector pane?  If not then why not set the values via VI Server and then (after closing the reference) run it via Call by Reference as illustrated?

 

There's a major race condition here int hat any other code COULD execute the VI in the time between you setting the controls and explicitly running it afterwards.  I don't see how to deal with this effectively.

wiebe@CARYA
Knight of NI

>So if I understand correctly, setting the Control values via VI Server works, but when you try to run it, it's already reserved and fails.

 

Setting the control values doesn't "work". It sets the values even if the VI is executing. It does function as expected, and it is useful in other cases, but it is not a solution to the problem.

 

>Hmm. Are the controls you are trying to set also on the connector pane?  If not then why not set the values via VI Server and then (after closing the reference) run it via Call by Reference as illustrated?

 

Because setting the controls sets the values even if the Vi is executing. Also, Call by Reference will set the controls to default, or won't run at all if an input is required.

 

And, as mentioned, you need the strict type of the VI. So you end up making a VI that calls Call By Reference for each CP you have. Even if you do this, you gain nothing compared to simply making a sub VI wrapper to do the call.

 

>There's a major race condition here int hat any other code COULD execute the VI in the time between you setting the controls and explicitly running it afterwards. 

 

Exactly. It's a big problem.

 

>I don't see how to deal with this effectively.

 

We can't at the moment.

 

AristosQueue (NI)
NI Employee (retired)

AH. The "Run VI" method is a completely different beast than the "Call By Reference". That I can explain.

 

Any given VI is set up to either run as a top-level VI or as a subVI. Remember that the top-level VI has a lot of work to do that other VIs do not -- locking other VIs so they cannot be edited, remembering refnums to automatically deallocate on idle, manages abort behaviors differently, and other tasks behind the scenes. Something that is running top-level cannot be called as a subVI. This is a fundamental restriction of how LV is architected and won't be changing -- won't even be changing in the NXG platform.

 

The "Run VI" method starts a VI running as a top-level VI. It's an independent entity, separate from its caller. The Call By Reference node runs the VI as a subVI. Thus a VI that is reserved for use as a subVI can be called by CBR but cannot do the "Run VI" method.

 

The Asynchronous Call By Reference has two modes: "call and forget" and "call and wait". The first runs as a top-level VI... the second runs as a subVI.

 

You asked for an option on VI Server to "open a new instance (not a clone)". You mean like "new from .vit" instance? You can do that. Just name all your VIs with the ".vit" file extension. Every time you call Open VI Reference, you'll get a new, independent VI unless you wire in the 0x2 flag (the one that says don't instantiate templates). If you want us to go further with that and allow a more general "duplicate this VI on open even though it is not a .vit", we could do that, but I severely doubt that we ever would -- your use case is pretty exotic. I'm not saying its invalid, just that I cannot imagine it ever getting to the top of a priority queue of feature requests.

 

I'm inclined to Decline the idea as "it just ain't ever likely to happen," but I'll leave it open and let the kudos surprise me. The automatic closing of ideas (if more years elapse than kudos count) will, I suspect, close this one eventually.

AristosQueue (NI)
NI Employee (retired)

Another workaround: For VIs that are not members of libraries, You could programmatically call "File >> Save As" and duplicate the VI and then call the Run VI method on the duplicate. Or literally just copy the file on disk to a new file name... as long as you're not changing directories, that would work. Wouldn't work for VIs in libraries, however, because the library wouldn't acknowledge the duplicate, and you cannot edit the library while its members are running.

AristosQueue (NI)
NI Employee (retired)

PS: I called your use case exotic. I figure I should explain. Your architecture may very well work for you. I am not saying you should abandon it. The style of programming you are describing has its pros and its cons. I am going to explain why I don't see it very often: for most apps, the cons outweigh the pros.

 

You have a running application and you're trying to inject functionality into it from outside the application without being a part of its expected event trajectory. This implies a whole lot of things to me about how you're handling your event infrastructure and the bubble-up/trickle-down of your event handling. Most apps I have ever seen would not be amenable to someone just injecting events freely from anywhere in the application... it wouldn't even be possible for an arbitrary subVI to get access to the event refnums needed to generate events. They build in specific test functions into the application that can be twiddled from the outside OR they build proper test harnesses for a submodule where the test harness creates and supplies the event refnum that the module will be monitoring.

 

You appear to be storing the event refnums in a functional global or similar structure that enables an arbitrary piece of code to acquire and fire the event. That's the exotic aspect... it's common in small scale architectures, but I don't think I've ever seen a large app that could afford that kind of leakage in its architecture. The number one reason I see start up companies fail with LabVIEW is some engineer builds a wildly successful test bench in version 1, and then the boss says, "Great, build a second one and make both write to the same test status report." And the system is so riddled with global variables (functional globals count) that they cannot just run two copies of their subVIs, so what should have been a simple "drop a second subVI node in parallel" turns into a big refactoring effort.

 

That's what makes your architecture distinct from most others that I see, and it's why I doubt this idea will garner many kudos... it wouldn't help most apps do better testing if they could do the kind of "spin up a new copy" that you're requesting.