Jo-Jo Posted October 11, 2008 Report Share Posted October 11, 2008 I'm sure I'm not the only one that has run up against this. Does anyone know of a way to keep references alive after closing, or just stopping, the top level VI of the hierarchy that opened them? I'm trying to implement a more distributed architecture (not really distributed in the networking sense, everything is on one PC), in which the different application instances must know what the other instances are doing. In particular when a panel closes, it needs to check to see if any others are open in order to determine what to write to an XML file I am using. I know I can just reacquire new references whenever I dynamically open a new top-level VI, but I feel this is sloppy, and resource intensive. I feel a much better way of doing business is to acquire all the references I need when I initialize the application, and then keep them alive in a global, or something else that allows communication between threads, and close them when I'm finished with them. Unfortunately LabVIEW doesn't like this sort of architecture, and I can't find a way to stop the garbage collection. Anybody have a work around, or do I just have to keep acquiring new references to resources? ~Jo-Jo Quote Link to comment
LAVA 1.0 Content Posted October 11, 2008 Report Share Posted October 11, 2008 QUOTE (Jo-Jo @ Oct 10 2008, 04:25 PM) I'm sure I'm not the only one that has run up against this. Does anyone know of a way to keep references alive after closing, or just stopping, the top level VI of the hierarchy that opened them? I'm trying to implement a more distributed architecture (not really distributed in the networking sense, everything is on one PC), in which the different application instances must know what the other instances are doing. In particular when a panel closes, it needs to check to see if any others are open in order to determine what to write to an XML file I am using. I know I can just reacquire new references whenever I dynamically open a new top-level VI, but I feel this is sloppy, and resource intensive. I feel a much better way of doing business is to acquire all the references I need when I initialize the application, and then keep them alive in a global, or something else that allows communication between threads, and close them when I'm finished with them. Unfortunately LabVIEW doesn't like this sort of architecture, and I can't find a way to stop the garbage collection.Anybody have a work around, or do I just have to keep acquiring new references to resources? ~Jo-Jo In the launched VI's, open a ref to its FP and keep it open as long as it runs. That will keep LV from cleaning up the VI. Ben Quote Link to comment
Francois Normandin Posted October 11, 2008 Report Share Posted October 11, 2008 If you launch your VI with a subVI call, then use Ben's solution. If you use Invoke Node, you can transfer the reference owner to the subvi by setting AutoDispose Ref = TRUE. QUOTE From NI Help (Invoke Node: Run VI)Auto Dispose Ref: Allows you to run a VI independently of the caller without opening its front panel immediately or opening another reference inside the target VI. If TRUE, the referenced VI transfers ownership of the reference from the calling VI to the VI that is running. This means LabVIEW disposes of the reference, along with the parallel data space, when the target VI goes idle, not when the VI that opened the reference goes idle. The reference can still be used by the calling VI until the target VI closes the reference. The calling VI does not need to close the reference unless the Run VI method returns an error. If the calling VI does close the reference, the target VI can abort and leave memory. If FALSE, LabVIEW automatically disposes of the VI reference when the VI that opened it goes idle. The default is FALSE. Quote Link to comment
jdunham Posted October 12, 2008 Report Share Posted October 12, 2008 QUOTE (Jo-Jo @ Oct 10 2008, 01:25 PM) I'm sure I'm not the only one that has run up against this. Does anyone know of a way to keep references alive after closing, or just stopping, the top level VI of the hierarchy that opened them? I'm trying to implement a more distributed architecture (not really distributed in the networking sense, everything is on one PC), in which the different application instances must know what the other instances are doing. In particular when a panel closes, it needs to check to see if any others are open in order to determine what to write to an XML file I am using. I know I can just reacquire new references whenever I dynamically open a new top-level VI, but I feel this is sloppy, and resource intensive. I feel a much better way of doing business is to acquire all the references I need when I initialize the application, and then keep them alive in a global, or something else that allows communication between threads, and close them when I'm finished with them. Unfortunately LabVIEW doesn't like this sort of architecture, and I can't find a way to stop the garbage collection. The other replies are right about ways to keep a VI's reference open, but it sounds like you want to keep the caller's reference open. I read your post a few times, but I still don't quite get it. Let's say you have a loader VI which kicks off the real app panel with VI Server. Why do you want to keep a ref to the caller, anyway? My first thought is that you should keep a list of all the spawned panels themselves, so that your manager can check whether those are still open or valid. But maybe I'm misconstruing what you really need. What good is a ref to a VI which is closed and stopped? To put it another way, if you have to make a special effort to defeat the LabVIEW garbage collection, maybe your design is not quite right. How are you using different "application instances"? Are you running separate built EXEs? You can't share a global between application instances, whether in EXEs or LV source code. A VI ref is dependent on the application instance, so how do you deliver the correct app instance to your top level VIs now? Even if you open the VI ref by name, you have to supply the app instance. Maybe it's just Friday afternoon and I am wiped out, so ignore my babbling if you have solved it already. Quote Link to comment
Aristos Queue Posted October 12, 2008 Report Share Posted October 12, 2008 Option 1: Create a subVI that uses an uninitialized shift register. As long as the subVI stays in memory it will retain its values. If it leaves memory and gets reloaded, it will have the default value for that shift register. So if every top-level VI calls the subVI, that subVI will stay in memory as long as any of their runs overlap each other. They can put their names or a reference to themselves or something into that subVI and take it out again when they stop running. The other top level VIs can query that subVI for "who else is in memory?" Option 2: Assume that all your top-level VI have some consistent naming convention. Use the Application property "All VIs in memory" and check the list for any other top-level VIs. Option 3: Obtain a single element queue by name and use it to share a list of names and/or references to the top-level VIs. Option 4 (probably closest to what you're looking for): Don't shut down your application. Make what you currently have as top-level VIs be sub components that are loaded and managed by a real top-level VI. Quote Link to comment
Yair Posted October 12, 2008 Report Share Posted October 12, 2008 QUOTE (Aristos Queue @ Oct 11 2008, 02:14 AM) So if every top-level VI calls the subVI, that subVI will stay in memory as long as any of their runs overlap each other. They can put their names or a reference to themselves or something into that subVI and take it out again when they stop running. The other top level VIs can query that subVI for "who else is in memory?" Stephen, that will only work for the names (and I'm not actually sure the OP only wants to hold VI references). As mentioned, most references in LabVIEW (not including queues or notifiers obtained by name. Good for you) are GC'd when the top level VI in the hierarchy which originally created them goes idle, even if the subVI holding the reference is held in memory. I would say that the solution to this would be to create a daemon (implemented as a dynamically called VI) which will be responsible for acquiring and handing out the references, but since there aren't enough details about the actual requirements of the app, it's hard to say. In any case, it's also important to note Jason's note about app instances. If these really are separate instances, the references will not help, as they will not work across the instance boundary. Quote Link to comment
TG Posted October 13, 2008 Report Share Posted October 13, 2008 QUOTE (normandinf @ Oct 10 2008, 09:54 PM) If you launch your VI with a subVI call, then use Ben's solution.If you use Invoke Node, you can transfer the reference owner to the subvi by setting AutoDispose Ref = TRUE. http://lavag.org/old_files/monthly_10_2008/post-10515-1223671959.png' target="_blank"> Thanks Norm. that just cleared up something I was trying to get my head around regarding this topic. Good answer. Quote Link to comment
Jo-Jo Posted October 14, 2008 Author Report Share Posted October 14, 2008 I had realized that I could call the VIs with an invoke node, and then just open and close its front panel, but I wanted to avoid having to load every hierarchy into memory, since it is likely that the end user will only be using two or three at a time (I have seven). In this particular case it won't matter much, as the program I'm writing isn't very large, so I'll probably take your advice. I've written programs before that used a separate VI that kept track of the others, but this has special difficulties of it's own that I wanted to avoid, and I was thinking down the road, if I have a really big distributed app which can't all be loaded into memory at once, how would I do it. The other obvious option is to pass the paths into the seperate hierarchies, so that they can all open their own references, but I'm not sure this is a good idea (I feel like the program resources might start stepping all over each other if I'm not careful). Also, when I spoke about application instances, I believe that I picked that up from some LabVIEW documentation somewhere (or maybe it was here) where it was said that one VI hierarchy is considered one application instance by the garbage collector so even if references are shared somewhere in the hierarchy, when the top-level VI in one of the hierarchy closes, all the references opened in that hierarchy close. ~Jo-Jo Quote Link to comment
Aristos Queue Posted October 14, 2008 Report Share Posted October 14, 2008 QUOTE (Jo-Jo @ Oct 13 2008, 11:49 AM) Also, when I spoke about application instances, I believe that I picked that up from some LabVIEW documentation somewhere (or maybe it was here) where it was said that one VI hierarchy is considered one application instance by the garbage collector so even if references are shared somewhere in the hierarchy, when the top-level VI in one of the hierarchy closes, all the references opened in that hierarchy close. An application reference is an instance of the *LabVIEW* application space itself, not your particular VI hierarchy. You can have many top-level VIs open in each application instance. Every Project Window that you open is a separate application instance. If you launch a new labview.exe on another machine, that's another application instance. Quote Link to comment
Francois Normandin Posted October 15, 2008 Report Share Posted October 15, 2008 QUOTE (TG @ Oct 12 2008, 02:45 PM) Thanks Norm. that just cleared up something I was trying to get my head around regarding this topic. Good answer. Be careful though with my screenshot, as the OpenG "Get VI reference" is for the current VI: you should put a reference to the VI you wish to call, not to the one that is calling. I only wanted to show the property nodes and I Code Captured it too quickly... Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.