代码之家  ›  专栏  ›  技术社区  ›  gius

带有ItemsControl的Silverlight 4内存泄漏

  •  2
  • gius  · 技术社区  · 14 年前

    在我们的SL4应用程序中Caliburn.微型,我们遇到了(另一个)内存泄漏。

    当源集合被更改(另一个集合被分配给ItemsControl的ItemsSource绑定到的ViewModel属性)时,原始集合和绑定数据模板中的实体不会被垃圾收集。尽管NotifyPropertyChanged的事件处理似乎是通过WeakReference在内部完成的,但似乎SL保留了对这些对象的另一个引用。所以每次我们从服务器刷新数据时,内存消耗就会增加。

    你知道怎么解决这个问题吗? 我真的不明白SL4怎么会出现这种错误!

    一些实验表明ItemsControl.Items.Clear项()可能会有帮助。有什么技巧可以在每次更改ItemsSource时简单地调用它吗?我唯一想到的是重写ItemsSourceProperty并在那里添加一个处理程序。

    编辑:

    • 通过RIA服务上下文加载实体,并将它们的集合存储在viewmodel的属性中
    • 通过RIA服务上下文刷新实体

    所发生的情况是,尽管实体得到刷新(可以在视图中看到),但内存消耗正在增加。

    如果没有绑定,刷新实体不会消耗更多的内存(可能会消耗更多内存,但随着GC完成其工作,内存消耗级别最终会返回)。

    如果清除上下文或只是创建一个新的上下文,那么最终也会收集内存。

    似乎这个问题与RIA服务有关。

    here .

    3 回复  |  直到 14 年前
        1
  •  2
  •   Gabe    14 年前

    更新:

    Silverlight 4 Service Release修复内存泄漏: http://timheuer.com/blog/archive/2010/09/01/silverlight-service-release-september-2010-gdr1.aspx

    Silverlight4已知数据模板存在内存泄漏问题。目前测试的方式有一个修正。

    用户“heuertk”是一个微软Silverlight开发人员…他解释了问题和修复的状态。。。

    http://forums.silverlight.net/forums/t/171739.aspx

        2
  •  1
  •   EisenbergEffect    14 年前

    据我所知,这个问题是Silverlight4本身的一个bug。但是,你说你遇到了 另一个

        3
  •  1
  •   Bruno Altinet    14 年前

    嘿,我在玩你的解决方案,我想出了这个解决方法,工作得很好,基本上你改变你的DataSrc类如下,唯一的问题是如何应用类似的Ria服务实体。我已经在使用T4来调整代码生成(对于次要的事情),但是我不确定是否可以在两者之间强制执行类似的操作。另外,我想问的是,你有没有用你的样本申请报告你的问题?额外的报告不会有什么坏处:)

        public class DataSrc  :INotifyDataErrorInfo
    {
        public string Name { get; set; }
    
        public IEnumerable GetErrors(string propertyName)
        {
            yield break;
        }
    
        public void InvokeEvent()
        {
            _weakLinkErrorChanged.OnEvent(this, new DataErrorsChangedEventArgs("Name"));
        }
    
        private WeakLinkErrorChanged<DataSrc, object> _weakLinkErrorChanged;
    
        public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged
        {
            add 
            { 
                 _weakLinkErrorChanged=new WeakLinkErrorChanged<DataSrc, object>(this);
                _weakLinkErrorChanged.ErrorsChanged += value;
            }
    
            remove { _weakLinkErrorChanged.ErrorsChanged -= value; }
        }
    
        public bool HasErrors
        {
            get { return false; }
        }
    }
    
    
    internal class WeakLinkErrorChanged<TInstance, TSource> where TInstance : class
    {
    
        private readonly WeakReference _weakInstance;
    
        public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
    
        public WeakLinkErrorChanged(TInstance instance)
        {
            if (instance == null)
            {
                throw new ArgumentNullException("instance");
            }
    
            _weakInstance = new WeakReference(instance);
        }
    
        public void OnEvent(TSource source, DataErrorsChangedEventArgs eventArgs)
        {
            var target = _weakInstance.Target as TInstance;
    
            if (target != null)
            {
                if(ErrorsChanged!=null)
                    ErrorsChanged(target, eventArgs);
            }
            else
                ErrorsChanged = null;
        }
    }