In the process of searching for my memory leaks in an application written in Silverlight (the last entry in my personal blog) I found an error in the
ChildWindow class, leading to a memory leak.
In WinDbg it looks like:
ModalWindow below in my example - the heir from ChildWindow
0: 000: x86>! Dumpheap -mt
05e4f830Address MT Size
07068c28 05e4f830 236
070ba900 05e4f830 236
total 0 objects
Statistics:
MT Count TotalSize Class Name
05e4f830 2 472 MLOY.MKNA.KarjaKompassi.ModalWindow
Total 2 objects
')
0: 000: x86>! Gcroot
07068c28Note: Roots found on stacks may be false positives. Run "! Help gcroot" for
more info.
Scan Thread 5 OSTHread 1880
Scan Thread 22 OSTHread 1034
Scan Thread 23 OSTHread 1878
Scan Thread 24 OSTHread 1f28
DOMAIN (062239E0): HANDLE (Pinned): 3cc12f8: Root: 07de4260 (System.Object []) ->
06ed1460 (MLOY.MKNA.KarjaKompassi.FeedingPlan.
Shell ) ->
06ed14dc (MS.Internal.CoreTypeEventHelper) ->
06ef0c54 (System.Collections.Generic.Dictionary`2 [[System.Int32, mscorlib], [MS.Internal.CoreTypeEventHelper + EventAndDelegate, System.Windows]]) ->
070ee840 (System.Collections.Generic.Dictionary`2 + Entry [[System.Int32, mscorlib], [MS.Internal.CoreTypeEventHelper + EventAndDelegate, System.Windows]] []) ->
070a68a8 (MS.Internal.CoreTypeEventHelper + EventAndDelegate) ->
070a6870 (System.Windows.
RoutedEventHandler ) ->
07068c28 (MLOY.MKNA.KarjaKompassi.
ModalWindow )
In the code it looks like (Reflector looked in System.Windows.Controls.dll on the class ChildWindow):
private void ChildWindow_LostFocus (object sender, RoutedEventArgs e)
{
...
Application.Current.RootVisual.GotFocus + = new RoutedEventHandler (this.RootVisual_GotFocus);...
}
public void Close ()
{
...
Application.Current.RootVisual.GotFocus - = new RoutedEventHandler (this.RootVisual_GotFocus);...
}
private void SubscribeToEvents ()
{
base.LostFocus + = new RoutedEventHandler (this.ChildWindow_LostFocus);}
We can subscribe several times (every time the window loses focus), but unsubscribe only once when we call Close ()
Decision:
In the
ChildWindow_LostFocus method,
replace the problem line with a pair:
Application.Current.RootVisual.GotFocus - = new RoutedEventHandler (this.RootVisual_GotFocus);
Application.Current.RootVisual.GotFocus + = new RoutedEventHandler (this.RootVisual_GotFocus);