Я добавляю несколько тысяч (например, 53 709) элементов в WinForms ListView.
Попытка 1 : 13 870 мс
foreach (Object o in list)
{
ListViewItem item = new ListViewItem();
RefreshListViewItem(item, o);
listView.Items.Add(item);
}
Это работает очень плохо. Первое очевидное решение - вызвать BeginUpdate / EndUpdate
.
Попытка 2 : 3,106 мс
listView.BeginUpdate();
foreach (Object o in list)
{
ListViewItem item = new ListViewItem();
RefreshListViewItem(item, o);
listView.Items.Add(item);
}
listView.EndUpdate();
Это лучше, но все же на порядок медленнее. Давайте отделим создание ListViewItems от добавления ListViewItems, так что мы найдем фактическую причину:
Попытка 3 : 2,631 мс
var items = new List<ListViewItem>();
foreach (Object o in list)
{
ListViewItem item = new ListViewItem();
RefreshListViewItem(item, o);
items.Add(item);
}
stopwatch.Start();
listView.BeginUpdate();
foreach (ListViewItem item in items)
listView.Items.Add(item));
listView.EndUpdate();
stopwatch.Stop()
Настоящее узкое место - это добавление элементов. Давайте попробуем преобразовать его в AddRange
, а не в foreach
Попытка 4: 2,182 мс
listView.BeginUpdate();
listView.Items.AddRange(items.ToArray());
listView.EndUpdate();
Немного лучше. Убедитесь, что узкое место не в ToArray ()
Попытка 5: 2,132 мс
ListViewItem[] arr = items.ToArray();
stopwatch.Start();
listView.BeginUpdate();
listView.Items.AddRange(arr);
listView.EndUpdate();
stopwatch.Stop();
Кажется, ограничение заключается в добавлении элементов в список.Возможно, другая перегрузка AddRange
, где мы добавляем ListView.ListViewItemCollection
, а не массив
. Попытка 6: 2141 мс
listView.BeginUpdate();
ListView.ListViewItemCollection lvic = new ListView.ListViewItemCollection(listView);
lvic.AddRange(arr);
listView.EndUpdate();
Что ж, не лучше.
Теперь пора растянуть:
Шаг 1 - убедитесь, что ни один столбец не установлен на «автоматическая ширина» :
Проверьте
Шаг 2 - убедитесь, что ListView не пытается сортировать элементы каждый раз, когда я добавляю один:
Проверить
Шаг 3 - Спросить stackoverflow:
Проверить
Примечание: Очевидно, что этот ListView является не в виртуальном режиме; поскольку вы не можете / не можете «добавлять» элементы в представление виртуального списка (вы устанавливаете VirtualListSize
). К счастью, мой вопрос не о представлении списка в виртуальном режиме.
Есть ли что-то, чего мне не хватает, что могло бы объяснить такое медленное добавление элементов в список?
Bonus Chatter
Я знаю, что класс Windows ListView может работать лучше, потому что я могу написать код, который делает это в 394 мс
:
ListView1.Items.BeginUpdate;
for i := 1 to 53709 do
ListView1.Items.Add();
ListView1.Items.EndUpdate;
, что по сравнению с эквивалентным кодом C # 1349 мс
:
listView.BeginUpdate();
for (int i = 1; i <= 53709; i++)
listView.Items.Add(new ListViewItem());
listView.EndUpdate();
на порядок быстрее.
Какое свойство оболочки WinForms ListView мне не хватает?