Screen.GetView() memory leak

Topics: Bugs
Jun 5, 2012 at 11:00 AM
Edited Jun 5, 2012 at 11:04 AM


I'm having some trouble with a memory leak and I can't figure out how to solve it. It appears when I use GetView() inside of a ChildWindow. The code looks like this:

public class TestDialogViewModel : Screen
        public TestDialogViewModel()
            ButtonList = new ObservableCollection<string>();
            for (int i = 0; i < 100; i++)
        public ObservableCollection<string> ButtonList { getset; }
        public void KeyDown()
            object view = GetView(null);
            var method = view.GetType().GetMethod("Close");
            if (method != null)
                method.Invoke(view, null);
<controls:ChildWindow x:Class="SilverlightApplication124.TestDialogView"
    d:DesignHeight="300" d:DesignWidth="400" 
    cm:Message.Attach="[Event KeyDown] = [Action KeyDown];">
    <Grid x:Name="LayoutRoot" Background="White" Width="100" Height="100">
        <ItemsControl ItemsSource="{Binding ButtonList}">
                    <Button Content="test" Width="100" Height="20" />

And I open the ChildWindow by using: 

        public void Click()
            TestDialogViewModel viewModel = new TestDialogViewModel();
            Caliburn.Micro.Execute.OnUIThread(() => windowManager.ShowDialog(viewModel));

Then I just open the ChildWindow, press a button to close and repeat. Looking in the task manager the memory just keeps going up with about 3 MB per click and never goes down.
Anyone knows how this works and how to solve it?

Jun 5, 2012 at 11:14 AM

Have you checked using a GC.Collect to ensure that the memory is truly not released correctly?

Note that since the view-model is not a singleton, and a new view-model is created every time , a new view is instantiated as well, and the memory will increase as expected. Try calling GC.Collect before opening the view model, and see what happens. As far as I can see, there is no memory leak in this scenario (nevertheless, the just closed view-model/view pair will be kept in memory until the system requires it or a collection pass is enforced).

Jun 5, 2012 at 12:31 PM
Edited Jun 5, 2012 at 12:33 PM

Thanx for the fast answer! 

I tried to put a GC.Collect() in the Click() method but it it didn't help. Also, there are a few other things that looks like a memory leak to me:

The memory in the taskmanager (Processes, iexplore.exe *32) keeps going up at a constant rate. In the past when I've thought I had a memory leak but it was really just a slow GC the memory would go up and then a bit down and so on. 

If I don't use my KeyDown() method and just press the X on the ChildWindow the memory increase from about 23 to 60 and then it stops (+- a few MB) even if I press 50 times.

Rather quickly I got over 500 MB and could probably get more by just continue to open and close the ChildWindow (using the KeyDown() method). 

Jun 5, 2012 at 2:18 PM

Uhmmm. I checked the GetView implementation, and I think that if a leak exists, it's not there.

Could you try to use a profiler to determine if the view-model instance is still alive, after closing the child view?

If you don't want to/can't use a profiler, just implement a finalizer and put a brakpoint there. Then create a button in the UI to force a GC.Collect. Start the application, create the child window, close it using the close button (not the KeyDown), force a GC.Collect and see if the breakpoint is hit; then, open a new child window, try to close with the KeyDown method, force a GC.Collect and check if the breakpoint is hit.