Видимая утечка памяти в DataGridView

Как заставить DataGridView освободить ссылку на связанный DataSet?

У нас есть довольно большой набор данных, отображаемый в DataGridView, и мы заметили, что ресурсы не освобождаются после закрытия DataGridView. Если пользователь несколько раз просматривает этот отчет, он в конечном итоге получает исключение нехватки памяти. Профилировщик памяти ANTS подтвердил, что DGV хранит ссылку, несмотря на то, что dgv.DataSource имеет значение null.


person Jerry Fernholz    schedule 09.11.2009    source источник


Ответы (6)


Есть ли у вас какие-либо события, зарегистрированные в DataGridView, например OnClick? Убедитесь, что вы отменили регистрацию всех событий, иначе сборщик мусора не будет

person SwDevMan81    schedule 09.11.2009
comment
Это не совсем правда; это DataGridView, который может видеть out через свои события, поэтому, если DataGridView удаляется, его события будут аннулированы. Вопрос лучше: что можно увидеть (старый) _3 _... - person Marc Gravell; 09.11.2009
comment
Да, событий много. Я читал это в другом месте, но, похоже, это не было причиной. - person Jerry Fernholz; 09.11.2009

Вызовите это, чтобы очистить DataGridView1:

datagridview1.DataSource = null;
datagridview1.Rows.Clear();
GC.Collect();

Как я им пользуюсь?

Я импортировал данные из в DataGridView1, а затем изучил содержимое и перенес их в DataGridView2.

Таким образом, он использовал 2,4 ГБ памяти, а затем, после вызова Clear, он упал до нормального уровня - для меня до 128 КБ.

person Corrpside    schedule 24.11.2014

Мы видели такое поведение с datagridviews, у которых есть источник данных, содержащий множество изображений, где datagridview загружается повторно. Установка DataSource для datagridview на null и выполнение Dispose для источника данных и GC.Collect перед каждой загрузкой, похоже, устраняет утечку.

person Frank Ball    schedule 07.12.2017

Вы закрываете весь Form? или просто DataGridView? Интересно, это какое-то кеширование в BindingContext. Вы можете попробовать использовать новый контекст привязки для DataGridView?

Также; как всегда, события двойной проверки и т. д. - в частности, любое использование захваченных переменных, поскольку это тонкий способ добавления зависимости (обратите внимание, что области захвата означают, что вы можете захватывать больше, чем вы думаете, если у вас есть сложные анонимные методы / лямбда-выражения).

Возможно, вам придется зайти в профилировщики или windbg, чтобы найти оставшуюся ссылку.

person Marc Gravell    schedule 09.11.2009
comment
Сетка данных находится в форме, которая закрывается каждый раз. Когда пользователь запускает новый отчет, создается новый экземпляр. - person Jerry Fernholz; 09.11.2009

Уловка, заставляющая DataGridView освобождать ресурсы, состоит в том, чтобы выполнить привязку через промежуточный объект BindingSource.

Тогда код будет выглядеть примерно так:

...
DataGridView dgvQueryResults;
DataTable m_dataTable;
BindingSource m_binder;

public void PopulateView()
{
  ...
  // Bind the data source through and intermediary BindingSource
  m_binder.DataSource = m_dataTable;
  dgvQueryResults.DataSource = m_binder;
  ...
}


/// <summary>
/// Frees lindering resources. Sets data bindings to null and forces 
/// garbage collection.
/// </summary>
private void ResetDataGridView()
{
  dgvQueryResults.DataSource = null;

  if (null != m_binder) m_binder.DataSource = null;
  m_binder = null;

  dataTable = null;

  // Force garbage collection since this thing is a resource hog!
  GC.Collect ();

  m_binder = new BindingSource ();
}

...
person Jerry Fernholz    schedule 09.11.2009
comment
Есть много веских причин использовать BindingSource, но это не одна из них. Если объекты не удаляются из-за того, что они зарегистрированы с помощью событий, использование BindingSource вообще не решает проблему. Также: редко есть веские причины позвонить GC.Collect(), и это не одна из них. - person Robert Rossney; 09.11.2009
comment
Microsoft предложила использовать BindingSource здесь: connect.microsoft.com/VisualStudio/ обратная связь / Вызов GC.Collect() необходим в этом случае, потому что пользователь может просматривать отчеты быстрее, чем сборщик мусора освобождает ресурсы, и вскоре приложение выйдет из строя с исключением нехватки памяти. Хотя, конечно, функцию отчетности можно было бы переписать, чтобы она выглядела лучше. Кстати, все это произошло в результате классического не тестирования с реалистичным набором данных 8] - person Jerry Fernholz; 10.11.2009

Вы не должны устанавливать для DataGridView значение null. Вы должны вызвать dispose для DataGridView вместо того, чтобы позволить ему правильно очистить себя, вместо того, чтобы добавлять дополнительную работу в GC для его обработки.

Кроме того, если у вас есть корневые ссылки на DataGridView, он никогда не будет удален (даже если вы вызовете Dispose ()). ГК считает, что он все еще жив. Вы должны проверить наличие корневых ссылок на него, то есть обработчиков событий, статических ссылок и т. Д., И сначала удалить их перед вызовом Dispose ().

person Dave Black    schedule 28.10.2010