Potential memory leak in MultiPolyLineVisual3D

I contacted Ab4d a long while back about binding a PointsCollection to the PositionsList of a MultiPolyLineVisual3D.  I believe the following code is what resulted from this discussion.  As data is added to the PointsCollection i have in another class ("s" below) I call the following two lines to force an update on the line the view.  It appears it is needed to set the PositionsList to a new list (or I believe null also works) and then reassign it to the PointsCollection in question, without the initial reassignment, it does not work. 

    _multiPolyLineVisual3D.PositionsList = new List<Point3DCollection>();
    _multiPolyLineVisual3D.PositionsList = s.PointsCollection;

We are currently testing the software for robustness and are doing many repeated actions which results in the above code being called many times.  As this happens there is a constant increase in the number of references to Point3D and Point4D objects i.e. these references are not being released somewhere.  If we re-run this test with the above two lines commented out the "leak" goes away.   Is there something I am doing wrong or some bug in the MultiPolyLineVisual3D that is causing this?

This leak could well be somewhere else in our code and I will have a look into this also, as yet we have not been able to find anything obvious.

Thanks, TIm
PositionsList is a typical WPF's DepancedyProperty and has its OnChange handler. But if you reset its value to the already assigned value, then the OnChange handler is not called.

So, if you would call:
_multiPolyLineVisual3D.PositionsList = s.PointsCollection;

and then again (I assume s.PointsCollection is the same object instance):
_multiPolyLineVisual3D.PositionsList = s.PointsCollection;

The _multiPolyLineVisual3D would not get any notification about the change.

Therefore the PositionsList needs to be changed "for real" to notify the MultiPolyLineVisual3D about the change. Currently, the best way to do this is to set it to null and then back to the previous value (do not create a new List<Point3DCollection> - this is just a useless waste of objects that gets to GC). But I am planning to work on improving that in the future.

I assume that you are testing those two lines of code in a loop that runs in a test environment and that the lines are newer shown in the UI.

Each changed line is registered by Ab3d.Utilities.LinesUpdater class that handles rendering and updating the 3D lines. After each change of PositionsList, a new version of the line is added to the internal collection of LinesUpdater (you can get the number of registered lines with checking the Ab3d.Utilities.LinesUpdater.Instance.RegisteredLinesCount property). When the 3D line is actually shown, then the LinesUpdater can clean its collection and remove the unused registered lines. If you change PositionsList many times without showing the lines, then you will see a lot of positions in the .Net heap. But once the line is shown, or when the _multiPolyLineVisual3D is collected by GC, then the internal collections will be also cleared (if no line is ever shown, you may need to call Ab3d.Utilities.LinesUpdater.Instance.Refresh method to force refreshing the list of lines - do this after _multiPolyLineVisual3D is collected by GC).

I have many tests to check this functionality. After your post, I have run them again and checked your use case in more details and as far I can see, the code is working properly. But maybe I am missing something.

LinesUpdater is crucial when the 3D lines are rendered with WPF 3D. But when Ab3d.DXEngine is used to render the 3D lines, then the LinesUpdater still collects the registered 3D lines, but once they are rendered by Ab3d.DXEngine, the lines are removed from the internal LinesUpdater collection.

Please try to simulate the 3D lines rendering in a real-world use case as much as possible. If some problems are found there, please provide more details so that I will be able to reproduce the problems.
Andrej Benedik

Forum Jump:

Users browsing this thread:
1 Guest(s)