03-15-2014 04:00 AM
Hi Guys:
i met a "Refnum is No Longer Valid" issue in following case:
1 In B.vi , "Open vi reference" of A.vi(option x100) , Start Asynchronous Call , and store the reference into a global variable
2 In C.vi, use "Wait On Asynchronous Call" to queue the status of the A.vi instance calling from B
Problem here is , when i use the global variable in C.vi , it shows the correct memory address but "Refnum is No Longer Valid" , i know there's already some discussion about this , saying that all the reference will be clean after vi finish , solution is like "The simple (and correct) solution is not to call the functional global by itself, but only to call it as a subVI." , i don't quite understand what does this mean , any suggestion ?
03-15-2014 06:14 PM - edited 03-15-2014 06:15 PM
Basically suppose you have your two top level VIs A and B. If you open a refnum in the hierarchy (any subVI) of the top level VI A and A terminates, that refnum will be automatically closed. The only kind of refnum where you can disable that are VISA refnums, by going into the LabVIEW Options and selecting the according checkmark.
It doesn't matter if you store the refnum in a global variable or a subVI (Intelligent Variable). As soon as the top level VI, in whose hierarchy a refnum was created goes idle (stops executing) LabVIEW automatically garbage collects that refnum and it is not anymore valid to be used in another top level hierarchy. By using either the Run VI or Call VI Asynchronous option, that VI is running as an independant top level VI and therefore independent of the refnum that was created in the original hierarchy that started your B VI.
Solution is either to make sure the refnum is only opened in the hierarchy of B VI, or make sure A VI stays active and running, until the refnum is not anymore needed.
03-16-2014 04:39 AM - edited 03-16-2014 04:40 AM
Seems like there's no good solution for this ,
The reason why i need to do like this is : i want to build those Vis into dll , export B.vi and C.vi as functions, so that i can load A.vi using B.vi asynchronously instead of starting another thread in c code , and i can use C to queue the status of A,vi, even abort A.vi using abort vi ....
What do you think i can do the mulithread inside labview, i just don't want to build a labview dll which require creating mulit thread in c ode.
03-16-2014 09:17 AM
adobefree@gmail.com wrote:
Seems like there's no good solution for this ...
Try "Call and Forget" (option0x80), as that starts a VI as independant of its caller. "Call and Collect" (0x100) creates a VI that is "owned" by its caller and will abort if its caller goes idle.
03-16-2014 09:25 PM - edited 03-16-2014 09:25 PM
Thank you, i wil try "Call and Forget" (option0x80) , but does that mean i can't get the results any more ?
03-17-2014 04:54 AM
adobefree@gmail.com wrote:
Thank you, i wil try "Call and Forget" (option0x80) , but does that mean i can't get the results any more ?
You'd need to use a different method to get the results.
Quick aside: I've never worked with a LabVIEW dll, but are you sure that your A, B and C VIs won't be all running under the same hierarchy? "Going Idle" doesn't mean the VI stops running; it means it isn't reserved for execution (i.e.. nothing that calls it is running). I would have expected all functions in a dll to be reserved together.
Working with independant VI hierarchies and the issue of reference lifetime is tricky, but also doable. So if you do need A to continue after B's VI hierarchy has stopped then I can describe it. But first double check that you need the complexity.
03-17-2014 07:33 AM
"So if you do need A to continue after B's VI hierarchy has stopped then I can describe it. But first double check that you need the complexity."
Yes, i do need this, could you help on this ?
03-19-2014 08:32 PM
Any update ?
03-20-2014 02:46 AM
adobefree@gmail.com wrote:
Any update ?
Sorry, I'm away at a conference at teh moment. Basically, when you have VI hierarchies that "live" for different times, then you have to make sure that every reference is created (and thus "owned") by something that is going to stay active. So if B launches A and then goes idle, the communication method to A (which will be used by C) must be created by A. The easy method for that is:
-- have B create a temporary Queue
-- pass it to A when launched (launch with 0x80 "Call and Forget")
-- have A create its communication queue (or User Event or whatever)
-- pass the comm queue refnum back to B using the temporary queue
-- B destroys the temporary queue, stores the comm queue somehow for C, and finishes.
-- C waits on the Com Queue for the result of A.
-- you also need a way for A to know that C has gotten the result so it can then finish