Home » SilverlightRSS

Memory Leak Issue with inline DataTemplates in Xaml

I have been trying to track down why some of the views in my Silverlight MVVM app are not being garbage collected and after a lot of testing it seems that having a DataTemplate inline in xaml prevents a usercontrol from being garbage collected.

If you create 2 very simple silverlight user controls like the following

Control A

    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.Resources>
            <DataTemplate x:Key="DataTemplateResource">
                <Border Height="100" Width="100" Background="blue">
                </Border>
            </DataTemplate>
        </Grid.Resources>
        <ContentControl ContentTemplate="{StaticResource DataTemplateResource}" />
    </Grid>

Control B 

    <Grid x:Name="LayoutRoot" Background="White">
        <ContentControl>
            <ContentControl.ContentTemplate>
                <DataTemplate>
                    <Border Height="100" Width="100" Background="blue">
                    </Border>
                </DataTemplate>
            </ContentControl.ContentTemplate>
        </ContentControl>
    </Grid>

So the only difference between these controls is that in Control A the DataTemplate is a resource and in Control B it is inline.

Now if you run the following code you can see that Control A will be garbage collected and Control B remains in memory. 

WeakReference a = new WeakReference(new ControlA());
WeakReference b = new WeakReference(new ControlB());

GC.Collect();
GC.WaitForPendingFinalizers();

bool isControlAAlive = a.IsAlive;  // This is falsebool isControlBAlive = b.IsAlive;  // This is true

The only thing I can think of is that this must be a Silverlight bug causing a reference to be created inside the control to stop it being garbage collected. If so hopefully they can fix it soon or if not they could provide guidance on how to structure xaml to avoid these memory leaks.

NOTE: This occurs on Silverlight 4 RC, seems to be fine in Silverlight 3.

 

24 Answers Found

 

Answer 1

This bug  applies to inline  Control Templates as well as Data Templates as you can see with this similar example

Control A

    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.Resources>
            <ControlTemplate x:Key="DataTemplateResource" TargetType="Button">
                <Rectangle Width="100" Height="100" Fill="Green" />
            </ControlTemplate>
        </Grid.Resources>
        <Button Template="{StaticResource DataTemplateResource}" />
    </Grid>

Control B

    <Grid x:Name="LayoutRoot" Background="White">
        <Button>
            <Button.Template>
                <ControlTemplate TargetType="Button">
                    <Rectangle Width="100" Height="100" Fill="Green" />
                </ControlTemplate>
            </Button.Template>
        </Button>
    </Grid>

As with the first example the only difference  is that with Control B the Control Template is inline instead of a resource  and again Control B is not garbage  collected while Control A is.

This is an issue  introduced in Silverlight 4. If you set the projects Target Silverlight Version to Silverlight 3 everything is garbage collected  fine.

 

Answer 2

If anyone from the Microsoft Silverlight team are reading this it would be great to know if this will be fixed for the Silverlight 4 release. These memory  leaks will make it impossible for us to release our app  and since DataTemplates and ControlTemplates would be used in most applications this should be a high priority fix.

 

Answer 3

kornfish - running the code  sample you have here in post-RC builds shows both reference  returning false.
 

Answer 4

 I have the same issues with my application,

since I have upgraded to RC from beta, my silverlight  app, showing a big leak  problem

since I know in fact, that my app  doesn't leaked in silverlight 3.0 and  also in silverlight 4.0 beta

I am suspecting that there is a problem in the GC, also I don't know if it is inline  DataTemplate issue  but it looks like a good explanation

since I don't have any strong references to event handlers (I am implementing WeakEvent pattern all over my code)

I have my self tried to pin down the problem, but with no success (until this post),

the most annoying symptom of the leak, that it is continues after the page is refreshed (even call to GC.Collect() doesn't help),

so the app is destroyed and reloaded, but the memory  doesn't released, instead doubled each time (as it showed in the Task Manager, at the browser  process)

after 3 refreshes, It is impossible to  work with the app, because it becoming very slow and not responsive (test on:  IE 7.0/IE8.0/Firefox 3.6)

my suggestion,

kornfish - please report this issue as you described to the Microsoft report bug  at http://connect.microsoft.com

 

Answer 5

Cheers Tim thats great news, can't wait for the final release.

 

Answer 6

Hi Tim,

   I just ran this code  with the new silverlight  4 release and the problem is still there. I created  a brand new Silverlight Application in Visual Studio 2010 Premium targeting Silverlight 4 and the controls  with an inline  data template or control  template are not being garbage  collected. If I switch the target silverlight version over to Silverlight 3 the garbage collection works fine.

This is causing  major memory  build ups in our app  and these are such common scenarios that it must be affecting a lot  of people.

 

Answer 7

We have the same trouble with our application in Silverlight 4.

Replacing all of the tens inline  datatemplates is unacceptably...

 

 

Answer 8

Also confirmed to still be leaking in SL4 RTW.  Moving an inline  ControlTemplate to the Resources section fixed the leak.

Now I have to start the task of changing and retesting a lot  of other functionality that may have inline templates.  Combine this with the AmbiguousMatchException breaking my production SL3 app  for end users, reliability so far of SL4 isn't looking good.

 

Answer 9

Hey all, the behavior seems to have regressed from a previous build I was using.  I'm investigating with the team now, using this repro.

 

Answer 10

Hi all, we're taking a look at this.  We've got some additional repros from others as well to add to our investigation.
 

Answer 11

I am also suffering due to this issue. I'm glad this thread exists explaining the exact cause, as I was unsure what was causing  it in my app. It's pretty terrible, as memory  starts to skyrocket quickly....
 

Answer 12

I have also this problem. I'm using Silverlight 4 (version 4.0.50401.0).

In my case the DataTemplete is inside  of DataGrid control:

 

            <data:DataGrid Grid.Row="0"
                       x:Name="grdDatos"
                       ItemsSource="{Binding ..., Mode=OneWay}"
                       AutoGenerateColumns="False">
                <data:DataGrid.Columns>

                    <data:DataGridTemplateColumn Header="..."
                                             SortMemberPath="..."
                                             Width="255">
                        <data:DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Vertical">
                                    <ToolTipService.ToolTip>
                                        <StackPanel Orientation="Vertical">
                                            <TextBlock Text="{Binding ..., Mode=OneWay}"/>
                                            <TextBlock Text="{Binding ..., Mode=OneWay}"/>
                                        </StackPanel>
                                    </ToolTipService.ToolTip>
                                    <TextBlock Text="{Binding ..., Mode=OneWay}"
                                           VerticalAlignment="Center"
                                           HorizontalAlignment="Left"
                                           TextAlignment="Left"/>
                                    <TextBlock Text="{Binding ..., Mode=OneWay}"
                                           VerticalAlignment="Center"
                                           HorizontalAlignment="Left"
                                           TextAlignment="Left"/>
                                </StackPanel>
                            </DataTemplate>
                        </data:DataGridTemplateColumn.CellTemplate>
                    </data:DataGridTemplateColumn> 
  
 

Answer 13

Hi Tim,

   Are there any updates on how this issue  is progressing or when it might be fixed?

Cheers

 

Answer 14

Also, the workaround doesn't work in all cases.  If your ControlTemplate contains a control  whose Template property is set to some other static resource, it will still leak.  In this case, making your template inline  actually seems to make the leak  go away.

For example, this will leak:

 

1    <Grid.Resources>
2 <ControlTemplate x:Key="MyContentTemplate"
3 TargetType="ContentControl">
4 <Grid>
5 <TextBlock Text="Hello" />
6 </Grid>
7 </ControlTemplate>
8
9 <ControlTemplate x:Key="MyButtonTemplate"
10 TargetType="Button">
11 <Grid>
12 <ContentControl Template="{StaticResource MyContentTemplate}" />
13 </Grid>
14 </ControlTemplate>
15
16 </Grid.Resources>

  But this will not:

  

1    <Grid.Resources>
2 <ControlTemplate x:Key="MyButtonTemplate"
3 TargetType="Button">
4 <Grid>
5 <ContentControl>
6 <ContentControl.Template>
7 <ControlTemplate TargetType="ContentControl">
8 <Grid>
9 <TextBlock Text="Hello" />
10 </Grid>
11 </ControlTemplate>
12 </ContentControl.Template>
13 </ContentControl>
14 </Grid>
15 </ControlTemplate>
16 </Grid.Resources>
 
 

Answer 15

I've also found that sometimes you can move the local template into app.xaml and then it will stop  leaking.

This leak  is a huge problem for any SL app  that is larger than a simple  hello world app, and considering one of the themes of SL4 is LOB apps, I'm surprised a patch hasn't been released to fix  this already.  My app easily now gets to 500MB-1GB RAM usage, where-as under SL3 it was no more than 50MB all the time.

If a fix is only going to be released in August, then I'm afraid that the silverlight  brand is going to be tarnished, up until now it has been a better and more performant alternative to flash, but to me SL4 is unusable in its current form.  Short of receiving official word within a few days that it's going to fixed real soon, we're abandoning our investment into silverlight and will go with the alternatives.

 

Answer 16

 There is another option actually, which we are considering.

 If you target your application toward Silverlight 3.0, then the leak  does not occur at all, even if it's loaded by the SL4 runtime.  Obviously if you do this, you can't use any of the new stuff in SL4.

 

Answer 17

 Hi, are there guarantees that this problem will be solved in August?

 

Answer 18

Additionally, I am seeing the items in memory  that are leaking still responding to LayoutUpdated event. Is this correct?

To illustrate this issue, please download the sample app  I have created  here: http://tinyurl.com/25qbyjx.

Once you download it, run  it in debug mode, and press the top button first a few times which will create  some leaky user  controls. Next, click the second button to remove them from the visual tree, and last press the 3rd button (garbage collect) just for good measure. The number displayed at the bottom is the number of leaky controls  (just to indicate they are indeed stuck in memory). Now, put a breakpoint in the LayoutUpdated event handler, and re-size the browser. Your break point will still be hit.

 

Answer 19

Hi tsheflin!

I write a small post talking how to identify this bug  on Silverlight code  with WinDBG, I used your code sample if you don't mind :)

http://www.luisguerrero.net/en/post/Detecting-memory-issues-with-Silverlight.aspx

All the best.

Luis Guerrero.

 

Answer 20

The memory  leak information is printed on "Output" window. [ This advantage is in "Debug" mode only. ] Example int _tmain() { int* ptr = NULL; ptr = (int*)malloc(sizeof(int)*20); for( int i=0; iIdea = i; #ifndef NDEBUG int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); // Get current flag flag |= _CRTDBG_LEAK_CHECK_DF; // Turn on leak-checking bit _CrtSetDbgFlag(flag); // Set flag to the new value #endif //free(ptr); printf("\n\nPress Enter..."); getch(); return 0; }
 

Answer 21

Hi all, thanks for being patient with us while we take a look at this.  We are evaluating a workaround in the interim which I've outlined below.  Our developers and testers have looked at this with a few but wanted to put our proposed workaround out there.  So far the workaround looks promising.

It involves using a dependency property and attaching to your data template.  Here's an example (assuming this is on MainPage.xaml):

 

1    public readonly static DependencyProperty TemplateWorkaroundProperty =
2    	   DependencyProperty.RegisterAttached("TemplateWorkaround", typeof(Int32), typeof(MainPage), null);
3    4    public static Int32 GetTemplateWorkaround(DependencyObject o)
5    {
6    return (Int32)o.GetValue(TemplateWorkaroundProperty);
7    }
8    9    public static void SetTemplateWorkaround(DependencyObject o, Int32 value)
10   {
11   	o.SetValue(TemplateWorkaroundProperty, value);
12   }

 and then in your XAML:

 

1    <Grid x:Name="LayoutRoot" Background="White">
2    		<ContentControl>
3    			<ContentControl.ContentTemplate>
4    			<DataTemplate local:MainPage.TemplateWorkaround="1">
5    					<Border Height="100" Width="100" Background="blue">
6    					</Border>
7    				</DataTemplate>
8    			</ContentControl.ContentTemplate>
9    		</ContentControl>
10   </Grid>
  As I mentioned, this is our current workaround we are evaluating.
 

Answer 22

Thanks Tim.  For me the workaround you suggest works for the simple  case of moving the inline  template to a resource, but found it didn't work for the case of nested templates (which is the hard one).  With a large app  with many themed controls, it is a nightmare to figure out which nested templates are causing  the leak, so that it can be moved around to and stop  the leak.

 

 

Answer 23

 Hi every body,

 

We are working on a project, and we are facing this problem. leaked memory  is affecting the performance of our product, and this is very annoying to make our Clients to press F5 each time the memory is crowded.

the project is a big one, I tried to track  Memory with WinDBG, but i am getting the same result as mentioned in this post :

http://www.luisguerrero.net/en/post/Detecting-memory-issues-with-Silverlight.aspx

We are looking for correcting this issue  from the Microsoft Team because other workarounds didn't worked for Us. 

 

Answer 24

hi  heuertk,

the workaround that you proposed is working well for me, especially if  I'm forcing GC.Collect()

but, I'm still facing a leak  problem when the browser is refreshed (F5) or browsed from the page,

when the browser is refreshed while the app  is running, all the memory  that was used by the app is remaining occupied,

I have tried to call GC.Collect() on the App_OnExit event, but with no great results.

so after the client is browsed through the site pages, with silverlight  apps running on them, after a while,

the browser is becoming non-responsive

 
 
 

<< Previous      Next >>


Microsoft   |   Windows   |   Visual Studio   |   Follow us on Twitter