I am having issues with garbage collection in a UI Framework I've built in WPF. I use memory leak in quotes because I think I understand the problem, but do not have a solution or some sort of work around.
This issue occurs when I create UIElements but do NOT display them. From a UI perspective, I am using a Virtualized List View (GridView). So all of the Rows are not displayed at once. In one of my use cases, I created an Export Rows features that has the ability to export all of the rows to a csv. Usually, the cells within the row are comprised of primitives like strings or ints.
Where it gets tricky is some of the cells are UIElements themselves, which is one of the reasons the list is virtualized (the cost to make some is time consuming and can be a memory hog). So I only create the UIElements when asked and then I don't even cache them (to make them be eligible for collection).
The issue occurs when I access the properties while I am enumerating through the row provider. The UIElements are created and returned, the data extracted from them, written to csv, and then the next row is looked at. In this loop, there are no references to these Rows (ViewModel Classes), so one would think they would be eligible for garbage collection. This appears to not be the case. Using .Net Memory Profiler, I have deduced that my "Out of Memory Exceptions" are a result the UIElements being held up in memory by a DispatcherOperation in a PriorityQueue (from Dispatcher). I assume this is because they're waiting to be displayed (but never do).
If I don't get an out of memory exception, EVENTUALLY these UIElements appear to be processed through the PriorityQueue (I'm guessing it gives up) and are garbage collected. This is the best case scenario. This seems to be fine when I'm dealing with a small number of Rows. But when we get into the 50,000 - 100k level, it's another story. I can assure you there are no other references to these ViewModels or to the UIElements themselves (outside of the DispatcherOperation).
Any thoughts on how I can fix this or get around this problem? Is there anyway to block this queuing of these undisplayed, and soon to be unused UIElements?
Edit 01/25/2013: I realized I might need to clear up specifically what is saved in memory. The row objects, because they don't have a reference to the UIElement, which are not saved in memory (this is good). Only the UIElements that are accessed via a Get accessor are sticking around in memory. The only reference to them is the PriorityQueue and nothing of my own code.
UIElement
s are created/destroyed, it'd be hard to help answer this. – Pyroelectricity