09-13-2017 07:44 AM - edited 09-13-2017 07:50 AM
I know this has been asked before, but I'm still unsure.
Suppose I have the following sub VI (which gets information about the available network interfaces).
https://i.imgur.com/2IJB3te.png
It has many .Net property and invoke nodes which use references from previous .Net nodes.
Is it best practice to explicitly close these references, or will LabVIEW automatically close them, once the VI has finished running, in a timely fashion ready for garbage collection (main VI still running)?
If they should be closed, there's then the question of "can I just close the parent reference" (as below)?
https://i.imgur.com/Zk15dP6.png
Or should all of them be closed individually?
https://i.imgur.com/Y436mO7.png
VIs also attached, both 2017 and 2010 versions.
Solved! Go to Solution.
09-13-2017 08:15 AM
Is it best practice to explicitly close these references, or will LabVIEW automatically close them, once the VI has finished running, in a timely fashion ready for garbage collection (main VI still running)?
Yes, you should close all references, LabVIEW won't do that for you.
If they should be closed, there's then the question of "can I just close the parent reference" (as below)?
No, that's not a good idea.
Or should all of them be closed individually?
Yes, that's the correct thing to do!
Regards, Jens
09-13-2017 08:17 AM
You're not closing objects. You're closing references to objects. An object will be released when the reference count is 0. So not closing child object, might even force the parent to stay open.
So closing the parent is not enough. You need to close all references you opened.
Note that Close Reference does except arrays. That might help a little bit.
>Is it best practice to explicitly close these references,
Absolutelly.
>or will LabVIEW automatically close them
No. Native references: yes, sometimes (or rather the refs will always be the same so it's no problem). .NET, ActiveX references: no.
>, once the VI has finished running,
Not when the VI finished running, unless it's running top level. LV might release some references when the VI goes to idle, but I wouldn't count on it. It's not good practice.
>in a timely fashion ready for garbage collection (main VI still running)?
LabVIEW has no garbage collection (although it does a good job pretending it does).
09-13-2017 09:16 AM
Thanks both for your replies. Very helpful.
wiebe@CARYA wrote:
You're not closing objects. You're closing references to objects.
This is the part I keep forgetting.
With that in mind, does this mean the order of closing shouldn't matter, as long as they are all closed and not used again?
The memory consumed by the .NET object would still be released through the .NET CLR garbage collection though, wouldn't it?
09-13-2017 09:24 AM
@matt.baker wrote:
Thanks both for your replies. Very helpful.
wiebe@CARYA wrote:
You're not closing objects. You're closing references to objects.
This is the part I keep forgetting.
With that in mind, does this mean the order of closing shouldn't matter, as long as they are all closed and not used again?
I'm inclined to say the order doesn't matter. I've never seen it matter, and in theory it shouldn't. (If you'll call some Close or Dispose method's the order will matter).
matt.baker wroteThe memory consumed by the .NET object would still be released through the .NET CLR garbage collection though, wouldn't it?
When the object is released by LV, .NET might clean up unreferenced objects. But if LV has a reference to those objects, they will not be unreferenced. So the .NET CLR will not consider them garbage.
09-13-2017 07:05 PM - edited 09-13-2017 07:18 PM
Just a couple of notes to add:
09-14-2017 02:41 AM
@tyk007 wrote:
3) "Close References" order only matters if you need to perform some sort of manual "close" or "dispose" action prior to completing your activities and the object in question is a wrapper around unmanaged references. Generally such classes should follow the IDisposable pattern and include the dispose hook in the Finalizer for the class (so that GC will call the Finalizer and release that memory for you). If you don't know or can't guarantee that this is the case then just follow the convention provided by the class author.
You've lost me on this one. So we don't need to close "pure" .NET objects? Do you mean LV automatically disposes objects when "the wire ends"?
09-14-2017 02:24 PM - edited 09-14-2017 02:35 PM
Sorry, the term "close" is overloaded here. What I was trying to say is that the order of when you call "Close References" on your objects (ordering between them) does not matter. For an individual reference however if the class you are using has a defined protocol for how you must indicate you are finished with that object you must follow that prior to calling "Close References" on an instance of it. For some classes this is a "Dispose" or "Close" method; in .NET there is a typical pattern for this (IDisposable) which has a "Dispose" method to help release unmanaged resources that would otherwise leak.
LabVIEW still doesn't automatically release references for ".NET objects" (purity aside) automatically until the top-level VI Hierarchy that created that reference goes idle. I believe this is generally the same reasoning as for all other reference-like types in LabVIEW (as mentioned here http://www.ni.com/tutorial/14393/en/).
So if I was still able to edit my post I would say:
Does that make more sense? I did sneak a 5th/6th one in there just for completeness.
09-15-2017 04:27 AM - edited 09-15-2017 04:35 AM
@matt.baker wrote:
With that in mind, does this mean the order of closing shouldn't matter, as long as they are all closed and not used again?
In theory yes, in practice there are buggy .Net assemblies out there which hand out "property" objects to the caller without those objects referencing their owner in any proper way but still maintaining some pointers that are owned by the owner. Releasing the owner before the owned object could then mean that the the owned object tries to reference something in the owner which has already vanished from memory. So I make it a rule to always close ActiveX and .Net objects in the reverse order in which I obtained them.
The memory consumed by the .NET object would still be released through the .NET CLR garbage collection though, wouldn't it?
Nope! As long as there is a reference to an object open the .NET CLR garbage collecter is required to not touch that object or REALLY BAD THINGS start to happen. In ActiveX you don't even have a garbage collector. Objects deallocate themselves as soon as the reference count reaches 0.
wiebe@CARYA wrote:
Not when the VI finished running, unless it's running top level. LV might release some references when the VI goes to idle, but I wouldn't count on it. It's not good practice.
Actually LabVIEW closes all refnum types when the top level VI in whose hierarchy the refnum was created goes idle. You only can disable that for VISA refnums in the options (yes the purple tag based (named) refnums like VISA and IMAQ too are also refnums).
But I make it a rule to not rely on that but instead close all refnums explicitly. Your object may be called in a way that simply releases its refnum automatically later on as your dynamically started deamon terminates but in 6 months from now you pull that VI library out of your "awsome program" and use it in your "totally awsome super program" using it in a way that creates those objects over and over again in a hierarchy that never goes idle and everything works fine during development and debugging but starts to explode badly once you deployed the app to a remote station in Antarctica after two months of continuously creating .Net objects without them ever being released!
09-15-2017 04:52 AM
There is a pragmatic approach:
Run the VI in a while loop (not continuous run).
Does the memory increase?
More references to close!