LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Closing .NET reference issue

Solved!
Go to solution

Hi guys,

I have very strange issue with closing my .NET references. I had simplified my program to this very simple sample, but problem has stayed. Close ref function is without error.

 

Class without explicit parent, containing only public const stringsClass without explicit parent, containing only public const strings

dett.png

Any ideas? Thx for any reply

0 Kudos
Message 1 of 7
(1,202 Views)
Solution
Accepted by topic author adamcoalman

Are you running this example in a single VI (not in a project)? And is what you shown the entire block diagram?

 

I think this example is probably a false 'positive' as a result of a race condition. Close Reference doesn't actually release memory, it simply un-pins the reference in the CLR to enable garbage collection when the next collection sweep occurs. A single VI ending execution in this example ends the VI Hierarchy. Ending a VI hierarchy always causes LabVIEW to release references created in that hierarchy and, in the case of .NET, destroying the App Domain that was created to host all the created .NET objects. This probably occurred before the garbage collection thread(s) have executed to release memory for dead objects in the CLR.

 

I think in this case you end up with this "false" result being indicated but the reality is all that memory is released when the App Domain is destroyed anyway.

 

Maybe an idea of your original use-case would be helpful to eliminate other problems.

 

Message 2 of 7
(1,160 Views)

One thing I should mention is that the statement regarding the App Domain is correct when running a single VI as the top level VI outside of a project. As far as I am aware, in a project there is only one App Domain created per platform - so references can be shared between VI hierarchies and one hierarchy ending doesn't destroy the App Domain.

0 Kudos
Message 3 of 7
(1,142 Views)

Well, thank you for your prompt answer, it was very helpful.

At first I briefly answer your questions:

Yes, it is a single VI - without project.

Yes, what I had shown was entire block diagram.

 

First helpful thing was the VI hierarchy, so I have added one unneccessary VI at the end.

Second thing was the standalone VI - without project.

 

When I have tried to combine these two things, it seems much better.

 

The third issue, what I haven't mentioned, was array of types, that I replace with simple TypeList, as you can see on image below. Before I have used Build Array and passed it as constructor parameter.

 

 

solution.png

 

dett_sol.png

0 Kudos
Message 4 of 7
(1,123 Views)

Just for curious people, here is my solution how to store all refs at one place, and at the and their chronological closing. Chronological because the first created reference has the lowest id, and the last created refernce has the highest id.

 

I use static class with ulong list, which return sorted array:ObjectList.png

 

 

There is neccessary convert reference to some number, because when you try to store directly objects, LV will create new references for them.

 

In LV code then just anywhere use calling static invoke node like that:

 

convertto64.png

and at the end of application pick up sorted array and one by one convert to ref and close:

 

releaserefs.png

 

Of course you can use just LV array of numbers as global var, for example. I like static classes in LV, because I can use only invoke and property node to acces them, without storing variables. (Yes I know that data are stored in CLR, instead of LV runtime)

0 Kudos
Message 5 of 7
(1,115 Views)

Just a couple of tips:

  • There is no guarantee that the reference numbers will be incrementing. Yes it typically works in this fashion for short-lived programs but the CLR doesn't provide this guarantee (it may GC and then provide a new reference in a previously used area of the heap). So be careful on relying on this behavior. For your use case I don't think there is a lot of risk as the program is short-lived and there are only a handful of objects.
  • The Close Reference Node can take an array of references, closing each in turn. The Type Cast Node can also take an array I believe though I haven't tried this with a common Object ref.
  • Your C# class uses a List<T> instance to store 'references' as you add them. List<T> guarantees ordering based on the chronological calls to the Add() methods as new items are always added to the end of the list (https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1.add?view=netframework-...). Therefore, if you are calling your Add() method(s) in a specific order, the items in the private List<T> are already in that order. So the LINQ OrderBy extension method call shouldn't be required. In fact, it relieves you of the potential issue I commented earlier regarding the incrementing aspect. 
0 Kudos
Message 6 of 7
(1,092 Views)

Thanks for your tips.

You are right, I shouldn't rely on reference number.

 

Unfortunately, my program isn't short lived, it will be running for weeks and months without restart, and every minute will be creating tens of new references, so there is a need correctly close them and release memory. So I think over, how to that most brightly. 

Maybe creating groups with related refs, and use the chronological principe of Add method within each of them. Because when I close parent reference first, descendants can't close after that.

 

The reason, why I have used OrderBy, is I don't want to care whether I use Add method in correct order. But there is a need to do that somehow smartly, then order them by number, as mentioned above.

0 Kudos
Message 7 of 7
(1,074 Views)