WPF application memory leak January 18, 2010Posted by wesaday in Programming, Technology.
Tags: CMilChannel HwndSource, WPF
I have had an issue with a memory leak in one of my WPF (v3.5 SP1) based applications for quite some time. I has been really hard to track down because the appliation runs for 5 days apparently just fine then crashed with an “Out Of Memory” exception. So I have been trying to use profilers and just about any other tool that I could find to try and track down what would be allocating memory on a continual basis and not letting it go. Imagine my surprise when running profilers that the “before” and “after” snapshots are virtually identical. Very frustrating.
I did find this blog entry here, http://blogs.msdn.com/jgoldb/archive/2008/02/04/finding-memory-leaks-in-wpf-based-applications.aspx, that disuss many memory leaks and fixes for them but nothing there exactly described my situation, or the meaning was not clear. The demostration application for the leaks has the leak in there but I am not doing what he did (that I know of) and he does not demonstrate how to work around the problem. Then I ran across this question on StackOverflow, http://stackoverflow.com/questions/801589/track-down-memory-leak-in-wpf, which described exactly what I was seeing. Which also pointed back to the first blog. So, after not thinking about it over the weekend and coming in fresh on Monday I looked again. I found this entry on StackOverflow, http://stackoverflow.com/questions/1705849/wpf-memory-leak-on-xp-cmilchannel-hwnd, which points out a very simple solution.
Apparently somewhere along the line, the application is getting confused as to who is doing the rendering. So messages are being allocated and sent, but no one is consuming them so they pile up until you run out of memory. The work around is to create a new HwndSource in the application constructor and that reregisters the window class with Windows and does not cause the confusion.
public partial class App : Application
new HwndSource(new HwndSourceParameters());
This appeared to work for me and hopefully will help someone else.