为什么不对Silverlight ContentControls进行垃圾收集? [英] Why are Silverlight ContentControls not garbage collected?

查看:67
本文介绍了为什么不对Silverlight ContentControls进行垃圾收集?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在研究为什么不对我的某些控件进行垃圾回收,并且注意到很容易防止从ContentControl继承的简单控件被破坏.这是一个示例:

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:

这是我自定义的ContentControl:

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>

后面有以下代码:

 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)
    {
    }



}

那么视图模型是:

  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)
    {

    }


}

现在,当我离开此页面并尝试使用GC.Collect()进行垃圾收集时,只要我未对Textbox中的文本进行任何更改,ContentControl和Page就会被GC破坏.但是,如果我编辑了一些文本并导航到页面之外,然后尝试使用GC.Collect(),则ContentControl不会收集垃圾.

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?

实际上,您可以在卸载时通过闪烁"控件的模板来强制GC收集控件:

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;
    }

我认为这会破坏当前的可视树,丢失树的第一个组件对其父对象(自定义控件)的引用.当重新加载控件时,它肯定会强制控件重新调用OnApplyTemplate.

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.

这是开发Silverlight控件而不泄漏的正确模式吗?如果是这样,让我感到有些奇怪的是,当控件卸载时,模板不会自动处理.

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.

对于这种行为的正确描述将非常值得赞赏,因为它正好成为Silverlight控件生命周期的核心.

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

推荐答案

我的经验表明,Silverlight中的内存泄漏是由前2个原因引起的:

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

  • Events =>确保在不需要时或在类析构函数中删除附加事件一次.
  • 模板=>解决方案在资源"部分定义模板

这篇关于为什么不对Silverlight ContentControls进行垃圾收集?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆