2010-08-20 3 views
2

В нашем приложении SL4, построенном на Caliburn.Micro, мы столкнулись с (другой) утечкой памяти.Утечка памяти Silverlight 4 с помощью ItemsControl

Устранено, кажется, что проблема вызвана ItemControl с пользовательским DataTemplate, связанным с коллекцией объектов IEnumerable, которые реализуют интерфейс INotifyPropertyChanged.

Когда исходная коллекция изменена (другая коллекция назначена свойству ViewModel, к которому привязан ItemsSource ItemsControl), entites в исходной коллекции и связанных DataTemplates не собираются с мусором. Хотя обработка событий NotifyPropertyChanged, по-видимому, выполняется внутренне через WeakReference, похоже, что SL сохраняет другую ссылку на эти объекты. Поэтому каждый раз, когда мы обновляем данные с сервера, потребление памяти увеличивается.

У вас есть вопросы, как решить эту проблему? Я действительно не могу понять, как эта ошибка может произойти в SL4!

Некоторые эксперименты предполагали, что вызов ItemsControl.Items.Clear() может помочь. Любой совет, как просто называть это каждый раз при изменении ItemsSource? Единственное, что приходит мне на ум, это переопределить ItemsSourceProperty и добавить туда обработчика.

EDIT: Оказалось, что утечка происходит в этой ситуации:

  • нагрузки лиц через контекст RIA услуг и хранить коллекцию из них в собственности ViewModel
  • связать ListView с пользовательскими данными шаблон собственности с коллекцией entites
  • обновить entites через контекст РИА услуги

что происходит, что Altho В то время как объекты становятся обновленными, что можно увидеть в представлении, потребление памяти растет.

Если нет привязки, обновление объектов не потребляет больше памяти (возможно, но уровень потребления памяти в конечном итоге возвращается обратно, когда GC выполняет свою работу).

Если вы очистите контекст или просто создадите новый, то также будет собрана память.

Похоже, что проблема связана с услугами RIA.

Я могу предоставить простой проект, который показывает проблему, если вы хотите.

ОБНОВЛЕНИЕ: утечка памяти, по-видимому, вызвана INotifyDataErrorInfo. Прочтите here.

+0

Спасибо, что предупредили меня об этой проблеме! Вы знаете, если это происходит в WPF? –

+0

Пока нет. Но я постараюсь подготовить простое демо для WPF и SL, чтобы воспроизвести проблему, чтобы мы увидели. У тебя та же проблема? До сих пор кажется, что даже RIA может каким-то образом повлиять на проблему ... – gius

+0

Просто для подтверждения: вы тестируете это в режиме деблокирования без приставки отладчика, правильно? –

ответ

2

UPDATE:

Silverlight 4 Service Release исправить Утечки памяти: http://timheuer.com/blog/archive/2010/09/01/silverlight-service-release-september-2010-gdr1.aspx

Silverlight 4 имеет известные проблемы утечки памяти с шаблонами данных. Существует исправление по тому, как оно протестировано в настоящее время.

Вот нить я следующее:

Пользователь "heuertk" является Microsoft Silverlight Developer ....он объясняет проблемы и статус исправления ...

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

1

Это мое понимание того, что именно этот вопрос является ошибкой в ​​Silverlight 4 самих. Однако вы говорите, что столкнулись с еще утечкой памяти. Вы определили, был ли этот вопрос связан с Caliburn.Micro, и если да, вы опубликовали его на форумах проектов? Если ошибка в CM, я бы попытался исправить это. Благодарю.

+0

Привет, Роб. Ну, хотя это не известная ошибка SL4, решаемая последней версией GDR1, похоже, что она связана с услугами RIA. См. Обновленный вопрос. В любом случае, большое спасибо за Caliburn-Micro - это действительно здорово! Если утечка была вызвана CM, я сначала попытаюсь ее исправить, а затем отправить исправление :-). – gius

+0

Привет, Роб. Мы в конечном итоге отслеживали утечку памяти - это не вызвано C.Micro, а самой SL (INotifyDataErrorInfo). Я написал об этом в блоге: http://baud.cz/blog/memory-leak-in-silvelright-with-inotifydataerrorinfo – gius

1

Эй, я немного поиграл с вашим решением, я придумал это обходное решение, которое работает очень хорошо, в основном вы меняете свой класс DataSrc следующим образом, единственная проблема заключается в том, как применять что-то подобное в Ria Services организация. Я уже использую 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; 
    } 
} 
Смежные вопросы