я додаю кілька тисяч (наприклад, 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 мені не вистачає?