Silverlight’s ProgressBar And Possible Memory Leaks

6 commentsWritten on February 25th, 2009 by
Categories: Memory Management, Silverlight

This has got to be the weirdest memory leak i've ever investigated. We have this kick-ass Silverlight application, but unfortunately it suffered from very high memory usage that went up rather rapidly. So i attached windbg to the browser's process, took a memory dump and checked out which objects were still available in the heap. Much to my surprise, pretty much everything we instantiated was retained in memory and never got removed from the heap.

So i started looking into the usual things: making sure disposable instances where disposed of properly, that evenhandlers were unregistered properly, etc. I went over the code and it seemed to be alright. Stepping through the code with a debugger verified that disposables were indeed disposed of, and that all event handlers were unregistered.

So why was pretty much everything kept in memory? Further research with windbg showed that every ProgressBar instance that was ever created (and we use a lot of them, basically every time we make a call to the application server) kept a reference to the UserControl it was placed on and thus, kept the UserControl and all the references it contained alive. In our case, that includes our presentation models and obviously all of the contained child UserControls.

The ProgressBar is defined like this:

<ProgressBar Height="40" Style="{StaticResource ourKickAssStyle}" VerticalAlignment="Center" Width="40" IsIndeterminate="True"/>

The key here is the usage of the IsIndeterminate property... setting this to true causes the ProgressBar to move continuously without respecting any current Value property. You know, basic stuff. The thing is... if i change the definition of the ProgressBar to this:

<ProgressBar Height="40" Style="{StaticResource ourKickAssStyle}" VerticalAlignment="Center" Width="40" />

The memory leak suddenly went away :)

Obviously, this isn't a solution because the ProgressBar now doesn't really indicate any progress and we need our kick ass custom animation to retain the coolness of the application.

So for some reason, when you set the ProgressBar's IsIndeterminate property to true, it actually keeps all of its references alive even when the ProgressBar control is removed from its parent control. Happy times.

We now have the following ugly method in one of our base UI classes:

        private static void StopProgressBars(DependencyObject dependencyObject)
        {
            var count = VisualTreeHelper.GetChildrenCount(dependencyObject);
 
            for (int i = 0; i < count; i++)
            {
                var child = VisualTreeHelper.GetChild(dependencyObject, i);
                if (child != null)
                {
                    var progressBar = child as ProgressBar;
 
                    if (progressBar != null)
                    {
                        progressBar.IsIndeterminate = false;
                    }
 
                    StopProgressBars(child);
                }
            }
        }
  • http://silverlight.Net/blogs/JustinAngel Justin-Josef Angel

    Hi Davy,

    Thanks, we’ve got an internal bug open on that and we’re trying to get this fixed for vNext.

    Thanks for blogging about this. It’s important for the community to generate this kind of knowledge.

    Sincerely,
    – Justin Angel
    Microsoft Silverlight Toolkit program manager

  • http://blog.functionalfun.net Samuel Jack

    I had a a similar bug with the WPF progress control when it was in indeterminate mode. It was a bit weirder though, because this bug would cause memory allocations of about 4k/sec starting from a few seconds after you closed the form containing the progress bar! It wasn’t as simple as it holding onto the parent object though: IIRC the allocations were all happening inside one of the unmanaged parts of WPF.

    I could never get a reliable reproduction of it though, so I haven’t been able to submit a bug to MSFT yet.

    In the end, I went with making a text based control of my own, shunning WPF animation in this scenario.

  • Rob

    Why would you use windbg (beside it’s coolness factor)? You can just as well load Sos in your immediate window in VS (.load sos)

  • Rob

    By the way, cool thing finding the bug.

  • http://davybrion.com Davy Brion

    @Rob

    i didn’t even know you could load sos in the immediate window :)

  • Nike NFL Jerseys

    2011 Nike NFL Jerseys are a brand sale with fast deliver,and Cheap NFL Jerseys are favorite by many fans.