3

I have a standard CRUD application that works with a fairly large amount of data. Different windows access different tables using Linq-To-SQL, and each window essentially has a grid with cells bound to the objects I'm displaying.

Here's a pretty standard use case of what's happening:

  1. Open Window A
  2. Close Window A - Window A is now still in memory but no longer visible.
  3. Open Window B
  4. Close Window B - Windows A and B are now both in memory and neither are visible.
  5. Open Window C
  6. As data is retrieved for Window C, resources for Window A are released.

So at any given time I have 2-3 windows held in memory, when all I should really have is one. I have even added disposal code to the closing event for these windows which sets all of the references I can think of to null.

I tried using the ANTS memory profiler, and I'm noticing that each window is set as a GC root. Is there a way to disable this behavior or somehow force the GC to collect from these windows?

Thanks!

PS: I have checked this link and it didn't resolve the issue.

EDIT: The problem is that the users are getting System.OutOfMemoryExceptions.

Community
  • 1
  • 1
Jake
  • 7,565
  • 6
  • 55
  • 68

2 Answers2

3

I was able to fix this with two updates. First, I was using Telerik controls on my child windows. The Telerik controls have to keep track of the root visual, so if they're instantiated only on child windows then on each instantiation they assume that the child window is the root visual and assign a static reference to it. By instantiating a telerik control on my main application window, that window was set as the root visual in the static reference.

The second update I made was to assign each child window's owner as my main application window. After doing this and profiling I found that child windows were no longer being set as GC roots.

Now my child windows get garbage collected automatically after they're closed, as soon as new memory is requested for another window.

Jake
  • 7,565
  • 6
  • 55
  • 68
2

Generally GC has a life of his own. By releasing resources you just notify it that resources are no longer needed. Due to performance constraints and platform specific implementations it takes some time to garbage collect.

What makes developers life easier - hurts performance sometimes. That's why in C/C++ you can own the memory and new/delete as you wish. And even there there are pools and other techniques, cause new/delete is not cheap.

Lastly, you need to identify the problem in your architecture. Why is this a problem for you? Getting out of memory? Swapping? Locally or on the server? Etc.

Zepplock
  • 28,655
  • 4
  • 35
  • 50
  • "Generally GC has a life of his own." - Even when I call GC.Collect() it doesn't release resources. It's as if something is holding these resources in place, but I don't know what could be doing this. I don't have any static references to these objects that should be collected - I've verified this with the profiler. I'm assuming the issue has something to do with each window being a GC root, but I don't know what to do about that since it seems built into WPF. – Jake Jan 25 '11 at 02:19
  • From your original post it seems that the resources are released but not immediately after calling GC.Collect(). Is that so? – Zepplock Jan 25 '11 at 02:30
  • The GC.Collect() doesn't seem to release the resources. They aren't released until much later down the line, around the same time that they're released when I don't call this method. – Jake Jan 25 '11 at 05:11
  • @Jake (and others) Collect does not do what you think it does. To actually force memory to release, you need to call WaitForPendingFinalizers. https://stackoverflow.com/a/13955187/3195477 – StayOnTarget Aug 25 '20 at 21:10