Почему мой WPF Treeview привязан к классам LinqToSql, являющимся проблемой памяти? - PullRequest
0 голосов
/ 08 января 2009

У меня есть приложение WPF, которое останавливается после нехватки памяти ...
Это в основном TreeView отображающие узлы, которые являются экземплярами Linq To Sql ИЛИ Сгенерированного класса ICTemplates.Segment. Там около 20 таблиц, косвенно связанных через ассоциации с этим классом в конструкторе OR.

<TreeView Grid.Column="0" x:Name="tvwSegments" 
                      ItemsSource="{Binding}" 
                      SelectedItemChanged="OnNewSegmentSelected"/>
<HierarchicalDataTemplate DataType="{x:Type local:Segment}" ItemsSource="{Binding Path=Children}"> 
...

// code behind, set the data context based on user-input (Site, Id)
KeeperOfControls.DataContext = from segment in tblSegments
   where segment.site == iTemplateSite && segment.id == iTemplateSid
   select segment;

Я добавил явное свойство Children в класс сегмента, который ищет другую таблицу с записями parent-child.

public IEnumerable<Segment> Children
{
  get
  {
    System1ConfigDataContext dc = new System1ConfigDataContext();
    return from link in this.ChildLinks
      join segment in dc.Segments on new { Site = link.ChildSite, ID = link.ChildSID } equals new { Site = segment.site, ID = segment.id }
      select segment;
  }
}

Остальное - привязка данных в сочетании с шаблонами данных для отображения каждого сегмента в виде набора элементов управления пользовательского интерфейса.

Я почти уверен, что дети загружаются по требованию (когда я расширяю родительский) в зависимости от времени отклика. Когда я расширяю узел с 70 дочерними элементами, требуется некоторое время, прежде чем дочерние элементы загружаются (диспетчер задач отображает использование Mem как 1000000K!) Если я расширю следующий узел примерно с 50 детьми, БУМ! OutOfMemoryException

Я запустил Профилировщик VS, чтобы копать глубже, и вот результаты

Сводная страница Время жизни объекта Распределение

В топ-3 входят Action, DeferredSourceFactory.DeferredSource и EntitySet (все классы .Net / LINQ). Единственные пользовательские классы - это Сегмент [] и Сегмент с номерами № 9 и № 10.

Я не могу придумать, как вести. В чем может быть причина?

Ответы [ 4 ]

1 голос
/ 09 января 2009

может быть использование окружения этого DataContext?

using(System1ConfigDataContext dc = new System1ConfigDataContext()){
  .... ?
}

также пытались ли вы использовать sql profiler ? может пролить свет на этот вопрос.

0 голосов
/ 09 января 2009

Похоже, проблема заключается в создании нескольких объектов S1DataContext , как указано Sirocco . Я попытался использовать утверждение, чтобы заставить Dispose и сделать его пригодным для сбора. Однако это привело к исключению ObjectDisposedException, которое я не могу понять.

  1. Элемент управления исходит из строки, которая устанавливает контекст данных DockPanel KeeperOfAllControls.
  2. [Внешний код] (отображается в стеке вызовов)
  3. Segment.Children.get (имеет блок использования с dc)
  4. Возвращаясь к строке на шаге 1 ... ObjectDisposedException запрос Linq использует tblSegments, который извлекается из локального экземпляра S1DataContext

В любом случае, я предполагаю, что есть что-то, что препятствует созданию и удалению нескольких DataContexts. Итак, Я пытался использовать Singleton DataContext .
. И это работает!

  • Элемент управления TreeView значительно более отзывчив, каждый пробный узел загружается максимум за 3-4 секунды.
  • Я вставляю GC.Collect (для проверки) перед каждой выборкой / поиском, и теперь использование памяти остается в пределах 200 000-300 000 КБ.

OR, сгенерированный System.Data.Linq.DataContext, похоже, не исчезнет, ​​если не будет удален явно (потребляя память). Попытка утилизировать его в моем случае не увенчалась успехом ... хотя обе функции имели свои собственные блоки использования (нет общего экземпляра DataContext). Хотя мне не нравятся Singletons, я делаю небольшой внутренний инструмент для разработчиков и, следовательно, пока не обращаю на него внимания. Ни один из примеров LinqToSql, которые я видел в Интернете ... не имел мандатов на вызовы Dispose.

Так что, думаю, проблема была исправлена. Спасибо всем людям, которые сделали все возможное, чтобы эта ошибка стала мелкой.

0 голосов
/ 09 января 2009

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

Не могли бы вы попробовать это;

public IEnumerable<Segment> Children
{
  get
  {
    System1ConfigDataContext dc = new System1ConfigDataContext();
    return from link in this.ChildLinks
      join segment in dc.Segments on link.ChildSite == segment.site && link.ChildSID == segment.id
      select segment;
  }
}
0 голосов
/ 09 января 2009

Вы пытались использовать глобальный DataContext вместо одного для каждого элемента?

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...