I have a WPF App which is grinding to a halt after running out of memory…
It is basically a TreeView displaying nodes, which are instances of Linq To Sql OR Generated class ICTemplates.Segment. There around 20 tables indirectly linked via associations to this class in the OR designer.
<TreeView Grid.Column='0' x:Name='tvwSegments' ItemsSource='{Binding}' SelectedItemChanged='OnNewSegmentSelected'/> <HierarchicalDataTemplate DataType='{x:Type local:Segment}' ItemsSource='{Binding Path=Children}'> ... // code behind, set the data context based on user-input (Site, Id) KeeperOfControls.DataContext = from segment in tblSegments where segment.site == iTemplateSite && segment.id == iTemplateSid select segment;
I’ve added an explicit property called Children to the segment class which looks up another table with parent-child records.
public IEnumerable<Segment> Children { get { System1ConfigDataContext dc = new System1ConfigDataContext(); return from link in this.ChildLinks join segment in dc.Segments on new { Site = link.ChildSite, ID = link.ChildSID } equals new { Site = segment.site, ID = segment.id } select segment; } }
The rest of it is data binding coupled with data templates to display each Segment as a set of UI Controls.
I’m pretty certain that the children are being loaded on-demand (when I expand the parent) going by the response time. When I expand a node with around 70 children, it takes a while before the children are loaded (Task manager shows Mem Usage as 1000000K!). If I expand the next node with around 50 children, BOOM! OutOfMemoryException
I ran the VS Profiler to dig deeper and here are the results
Summary Page Object Lifetimes Allocation
The top 3 are Action, DeferredSourceFactory.DeferredSource and EntitySet (all .Net/LINQ classes). The only user-classes are Segment[] and Segment come in at #9 an #10.
I can’t think of a lead to pursue.. What could be the reason ?
The issue seems to be the creation of multiple S1DataContext objects as Sirocco referred to. I tried the using statement to force a Dispose and make it eligible for collection. However it resulted in an ObjectDisposedException that I can’t make sense of.
Anyways so i assume that there is something that prevents multiple DataContexts from being created and disposed. So I tried a Singleton DataContext.
And it works!
The OR generated System.Data.Linq.DataContext doesn’t seem to go away unless it is disposed explicitly (eating memory). Trying to Dispose it in my case, didn’t pan out.. even though both functions had their own using blocks (no shared instance of DataContext). Though I dislike Singletons, I’m making a small internal tool for devs and hence don’t mind it as of now.. None of the LinqToSql samples I saw online.. had Dispose calls mandated.
So I guess the problem has been fixed. Thanks to all the people that acted as more eyeballs to make this bug shallow.