Очевидная утечка памяти в DataGridView - PullRequest
5 голосов
/ 09 ноября 2009

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

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

Ответы [ 6 ]

3 голосов
/ 09 ноября 2009

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

1 голос
/ 08 декабря 2017

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

1 голос
/ 24 ноября 2014

Позвоните, чтобы очистить DataGridView1:

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

Как мне это использовать?

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

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

1 голос
/ 09 ноября 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 ();
}

...
1 голос
/ 09 ноября 2009

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

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

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

0 голосов
/ 28 октября 2010

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

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

...