Why are Silverlight ContentControls not garbage collected?

你离开我真会死。 提交于 2019-12-09 12:15:09

问题


I've been investigating why some of my controls aren't being garbage collected and noticed it's easy to prevent simple controls that inherit from ContentControl from ever being destroyed. Here's an example:

Here is my custom ContentControl:

 public class MyCustomControl : ContentControl
{

    public MyCustomControl()
    {
        Debug.WriteLine("Constructed");
    }

    ~MyCustomControl()
    {
        Debug.WriteLine("Destroyed");
    }
}

Now if I put it on a page like so:

<navigation:Page x:Class="SimpleTestBed.Views.CustomControl" 
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
       xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
       mc:Ignorable="d"
       xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
             xmlns:local="clr-namespace:SimpleTestBed"
       d:DesignWidth="640" d:DesignHeight="480"
       Title="CustomControl Page">
<Grid x:Name="LayoutRoot">

    <StackPanel>
        <local:MyCustomControl>
            <TextBox Text="{Binding SomeProperty,Mode=TwoWay}"></TextBox>
        </local:MyCustomControl>
    </StackPanel>

</Grid>

With the following code behind:

 public partial class CustomControl : Page
{
    public CustomControl()
    {
        InitializeComponent();

        this.DataContext = new CustomControlViewModel();

        this.Unloaded += new RoutedEventHandler(OnUnloaded);
    }

    void OnUnloaded(object sender, RoutedEventArgs e)
    {
        this.DataContext = null;
    }

    // Executes when the user navigates to this page.
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
    }



}

Then the view model is:

  public class CustomControlViewModel : INotifyPropertyChanged
{

    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        RaisePropertyChanged(propertyName);
    }
    private void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
    #endregion


    private string _someProperty = "Initial Value";
    public string SomeProperty
    {
        get { return _someProperty; }
        set
        {
            if (_someProperty != value)
            {
                string oldValue = _someProperty;
                _someProperty = value;
                OnPropertyChanged("SomeProperty");
                OnSomePropertyChanged(oldValue, value);
            }
        }
    }



    protected virtual void OnSomePropertyChanged(string oldValue, string newValue)
    {

    }


}

Now when I navigate away from this page and try garbage collecting with GC.Collect(), as long if I've made no changes to the text in the Textbox, the ContentControl and Page are destroyed as expected by the GC. But if I've edited some text and navigated away from the page and then tried to GC.Collect(), the ContentControl doesn't get garbage collected.

Can anyone explain this behavior?

Actually, you can force the GC to collect the control by 'flickering' the Template of the control when you unload:

  void MyCustomControl_Unloaded(object sender, RoutedEventArgs e)
    {
        Debug.WriteLine("MyCustomControl Unloaded");
        ControlTemplate oldTemplate = this.Template;
        this.Template = null;
        this.Template = oldTemplate;
    }

I presume this destroys the current visual tree losing references of the tree's first component to its parent (the custom control). It certainly forces the control to recall OnApplyTemplate when the control is reloaded.

Is this the correct pattern for developing Silverlight controls without leaking? If so, it strikes me as a bit bizarre that the template isn't disposed automatically when the control unloads.

A good account of this behavior would be much appreciated as it goes right to the heart of the life-cycle of Silverlight controls.


回答1:


My experience showed that memory leaks in Silverlight are coused by top 2 reason :

  • Events => Make sure that you remove attached events once when it is not needed or in class destructor.
  • Templates => Solution define templates in Resource section


来源:https://stackoverflow.com/questions/4287958/why-are-silverlight-contentcontrols-not-garbage-collected

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!