Я добавляю несколько тысяч (например, 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
). К счастью, мой вопрос заключается не в представлении списка в виртуальном режиме.
Есть ли что-нибудь, чего я не вижу, что может объяснить добавление элементов в список так медленно?
Бонус-чат
Я знаю, что класс ListView Windows может работать лучше, потому что я могу написать код, который делает это в 394 ms
:
ListView1.Items.BeginUpdate;
for i := 1 to 53709 do
ListView1.Items.Add();
ListView1.Items.EndUpdate;
который по сравнению с эквивалентным кодом С# 1,349 ms
:
listView.BeginUpdate();
for (int i = 1; i <= 53709; i++)
listView.Items.Add(new ListViewItem());
listView.EndUpdate();
на порядок быстрее.
Какое свойство оболочки WinForms ListView отсутствует?