views:

708

answers:

3

Application Background

Our platform is a click-once WPF application. We have a "shell" that contains a navigation menu structure and it hosts our own custom "page" classes. When you navigate to a new page, we swap out the content of the shell (essentially).

Problem

So, I work for a company that is working on a extremely large software project. We have much code that we found memory issues with.

The problem is that there are plenty of places in our application were events are wired and never unwired. I'm not sure why developers were doing this, I'm guessing that they expected the objects to get cleaned up each time a user navigates to a new "page".

We don't have the option of refactoring every page (in this release). Is there a way with C# to remove all references from an object? (Therefore allowing the garbage collector to throw that object away, along with all of it's internal references)

We are trying to get this memory back, but it is quite complicated to find objects are still referencing our pages (object references), when we have WPF to deal with.

We have looked at the visual and logical trees and used profiling applications to help us to manually clean things up (for proving out the idea) and this proved to be extremely hard as well.

I sat back and thought, why are we doing all this work to find object references, can't we just "dereference" this "page" when it is closed?

Which brings me here :)
Any help is greatly appreciated!


UPDATE 1

In the comments the following was asked:

Q: Does the app. actually have memory problems? How are these exhibited/detected? Or is this memory hanging around until a GC2 happens? – Mitch Wheat

A: It has memory problems. If we leave a page (property that holds the page gets set to a new object) the old object never gets collected by the garbage collector. So memory just keeps on growing. If our company started over, with this application. The first thing we should look at would be implementing WeakEvent Patterns and using more Routed Commands in WPF.

UPDATE 2

I was able to come up with my own solution.

A: 

If a hole page is going out of scope, including all underlying data, the GC will collect it. Eventually. However if that page is being referenced by anything that is still in scope, the page and all of its data will remain in memory and the GC will not be able to collect it.

As far as I know there is no easy button when it comes to fixing bad memory management. This means the only, in my opinion, is to do the work to clean up references. This will make it easier for the GC to collect objects that are out of scope.

You can suggest to the GC to go through its algorithm to see if anything can be collected by calling GC.Collect(). However this will do very little besides waste CPU cycles unless the data is truly out of scope.

Question for Phobis, How much memory is your application using?

EDIT:

Link to CLR Profiler 2.0 which should work for .net3.5 apps. http://www.microsoft.com/downloads/details.aspx?familyid=a362781c-3870-43be-8926-862b40aa0cd0&displaylang=en

Tony
+1  A: 

Have you used the CLRProfiler? I find this pretty good at finding objects and also finding what holds a reference to them.

This "How To" page...

http://msdn.microsoft.com/en-us/library/ms979205.aspx

... links to the download site.

However, I think the answer to your question is "no". There isn't a way of saying "object foo is no longer required - collect it please regardless of whether it's rooted or not". Collecting a rooted object could introduce all sorts of badness into your app.

Martin Peck
+1  A: 

I implemented WeakEvents to solve this issue.

Unfortunately, Microsoft recommends that you use their WeakEventManager as a base class and create a manager type for EACH event in your application!!! I tried to write a manager that inherits from this base and get it to be more "generic" (not in the C# term for generic). This "common" Event manager was not possible with Microsoft's base class. I had to write a Event manager from scratch.

Thank you for any help posted to this question.

Phobis