dodaję kilka tysięcy (np. 53 709) elementów do WinForms ListView.
Próba 1 :13,870 ms
foreach (Object o in list)
{
ListViewItem item = new ListViewItem();
RefreshListViewItem(item, o);
listView.Items.Add(item);
}
To działa bardzo źle. Oczywistym pierwszym rozwiązaniem jest zadzwonić BeginUpdate/EndUpdate
.
Próba 2 :3,106 ms
listView.BeginUpdate();
foreach (Object o in list)
{
ListViewItem item = new ListViewItem();
RefreshListViewItem(item, o);
listView.Items.Add(item);
}
listView.EndUpdate();
To jest lepsze, ale wciąż o rząd wielkości zbyt wolno. Oddzielmy tworzenie ListViewItems od dodawania ListViewItems, aby znaleźć rzeczywistego winowajcę:
Próba 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()
Prawdziwym wąskim gardłem jest dodawanie elementów. Spróbujmy przekonwertować go AddRange
raczej na plikforeach
Próba 4: 2,182 ms
listView.BeginUpdate();
listView.Items.AddRange(items.ToArray());
listView.EndUpdate();
Trochę lepiej. Upewnijmy się, że wąskie gardło nie znajduje się wToArray()
Próba 5: 2,132 ms
ListViewItem[] arr = items.ToArray();
stopwatch.Start();
listView.BeginUpdate();
listView.Items.AddRange(arr);
listView.EndUpdate();
stopwatch.Stop();
Wydaje się, że ograniczeniem jest dodawanie elementów do widoku listy. Może inne przeciążenie AddRange
, w którym dodajemy ListView.ListViewItemCollection
zamiast tablicy
Próba 6: 2,141 ms
listView.BeginUpdate();
ListView.ListViewItemCollection lvic = new ListView.ListViewItemCollection(listView);
lvic.AddRange(arr);
listView.EndUpdate();
Cóż, nie jest lepiej.
Teraz czas się rozciągnąć:
Krok 1 - upewnij się, że żadna kolumna nie jest ustawiona na „szerokość automatyczną” :
Czek
Krok 2 - Upewnij się, że ListView nie próbuje sortować elementów za każdym razem, gdy je dodam:
Czek
Krok 3 - Ask stackoverflow:
Czek
Uwaga: Oczywiście ten ListView nie jest w trybie wirtualnym; ponieważ nie możesz / nie możesz „dodawać” elementów do wirtualnego widoku listy (ustawiasz VirtualListSize
). Na szczęście moje pytanie nie dotyczy widoku listy w trybie wirtualnym.
Czy jest coś, czego mi brakuje, co mogłoby tłumaczyć tak powolne dodawanie elementów do widoku listy?
Bonus Chatter
Wiem, że klasa Windows ListView radzi sobie lepiej, ponieważ mogę napisać kod, który robi to w 394 ms
:
ListView1.Items.BeginUpdate;
for i := 1 to 53709 do
ListView1.Items.Add();
ListView1.Items.EndUpdate;
co w porównaniu z równoważnym kodem C # 1,349 ms
:
listView.BeginUpdate();
for (int i = 1; i <= 53709; i++)
listView.Items.Add(new ListViewItem());
listView.EndUpdate();
jest o rząd wielkości szybszy.
Jakiej właściwości opakowania WinForms ListView brakuje?