Я добавляю несколько тысяч (например, 53 709) элементов в WinForms ListView.
Попытка 1 :13,870 ms
foreach (Object o in list)
{
ListViewItem item = new ListViewItem();
RefreshListViewItem(item, o);
listView.Items.Add(item);
}
Это работает очень плохо. Первое очевидное решение - позвонить BeginUpdate/EndUpdate
.
Попытка 2 :3,106 ms
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 ms
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 ms
listView.BeginUpdate();
listView.Items.AddRange(items.ToArray());
listView.EndUpdate();
Чуть лучше. Будем уверены, что узкое место не вToArray()
Попытка 5: 2,132 ms
ListViewItem[] arr = items.ToArray();
stopwatch.Start();
listView.BeginUpdate();
listView.Items.AddRange(arr);
listView.EndUpdate();
stopwatch.Stop();
Ограничение похоже на добавление элементов в список. Может быть, другая перегрузка AddRange
, где мы добавляем, ListView.ListViewItemCollection
а не массив
Попытка 6: 2,141 ms
listView.BeginUpdate();
ListView.ListViewItemCollection lvic = new ListView.ListViewItemCollection(listView);
lvic.AddRange(arr);
listView.EndUpdate();
Что ж, не лучше.
Пришло время растянуть:
Шаг 1 - убедитесь, что ни один столбец не настроен на автоматическую ширину :
Проверьте
Шаг 2 - убедитесь, что ListView не пытается сортировать элементы каждый раз, когда я их добавляю:
Проверьте
Шаг 3 - спросите stackoverflow:
Проверьте
Примечание. Очевидно, что этот ListView не находится в виртуальном режиме; поскольку вы не / не можете «добавлять» элементы в представление виртуального списка (вы устанавливаете VirtualListSize
). К счастью, мой вопрос не о представлении списка в виртуальном режиме.
Есть ли что-то, чего мне не хватает, что могло бы объяснить медленное добавление элементов в список?
Бонусный чат
Я знаю, что класс Windows ListView может работать лучше, потому что я могу написать код, который делает это в 394 ms
:
ListView1.Items.BeginUpdate;
for i := 1 to 53709 do
ListView1.Items.Add();
ListView1.Items.EndUpdate;
что по сравнению с эквивалентным кодом C # 1,349 ms
:
listView.BeginUpdate();
for (int i = 1; i <= 53709; i++)
listView.Items.Add(new ListViewItem());
listView.EndUpdate();
на порядок быстрее.
Какое свойство оболочки WinForms ListView мне не хватает?