Подумайте о том, что происходит, когда вы заполняете несвязанный DataTable
одной строкой из DataReader
: создается DataRow
, заполняется из DataReader
и добавляется в коллекцию Rows
. Затем при создании привязки DataGridView
извлекает данные из таблицы и создает представление на экране.
Что происходит, когда вы заполняете DataTable
, чья привязка к DataGridView
включена? Целый беспорядок обработки событий. Каждый раз, когда вы изменяете связанное свойство, возникает событие с измененным свойством, и связанный с ним элемент управления обрабатывает его. Это не происходит 300 000 раз, это происходит 300 000 раз для каждого столбца .
Что, если вы отключите это, и обновите связанный элемент управления только изредка? Посмотрите на этот метод:
private void PopulateDataTable()
{
int rowCount = 10000;
bindingSource1.RaiseListChangedEvents = false;
for (int i = 0; i < rowCount; i++)
{
DataRow r = DT.NewRow();
for (int j = 0; j < ColumnCount; j++)
{
r[j] = "Column" + (j + 1);
}
DT.Rows.Add(r);
if (i % 500 == 0)
{
bindingSource1.RaiseListChangedEvents = true;
bindingSource1.ResetBindings(false);
Application.DoEvents();
bindingSource1.RaiseListChangedEvents = false;
}
}
bindingSource1.RaiseListChangedEvents = true
}
Вы должны вызвать ResetBindings, чтобы принудительно обновить связанный элемент управления. Это требует времени, потому что вы не можете обойтись без затрат на строительство DataGridViewRow
объектов, но вывоз событий - значительное улучшение. На моей машине, если я заполняю 10-столбец, 10000 строк DataTable
, который связан с DataGridView
, это займет 2900 миллисекунд. Если я оставляю привязку данных отключенной все время, это занимает 155 миллисекунд. Если я сбрасываю привязки каждые 500 строк, это займет 840 миллисекунд.
Конечно, если бы я заполнял таблицу из 300 000 строк, я бы не сбрасывал привязки каждые 500 строк; Я, вероятно, сделаю это один раз на отметке 500 строк, а затем выключу, пока операция не завершится. Но даже если вы сделаете это, вам нужно будет вызывать Application.DoEvents
каждый раз, чтобы пользовательский интерфейс мог реагировать на события.
Редактировать
Не берите в голову этот бит о Application.DoEvents
; вам не нужно этого делать, если вы заполняете таблицу в фоновом режиме.
Но вам нужно убедиться, что вы сбрасываете привязки в ProgressChanged
обработчике событий BackgroundWorker
, а не в методе DoWork
. И вы столкнетесь с целым миром боли, если на самом деле позволите пользователю редактировать данные в ограниченном DataGridView
при заполнении его источника данных в другом потоке.