estoy agregando algunos miles (por ejemplo, 53,709) elementos a un ListView de WinForms.¿Cómo acelerar la adición de elementos a un ListView?
Intento 1: 13,870 ms
foreach (Object o in list)
{
ListViewItem item = new ListViewItem();
RefreshListViewItem(item, o);
listView.Items.Add(item);
}
Esto funciona muy mal. La primera solución obvia es llamar al BeginUpdate/EndUpdate
.
Intento 2: 3,106 ms
listView.BeginUpdate();
foreach (Object o in list)
{
ListViewItem item = new ListViewItem();
RefreshListViewItem(item, o);
listView.Items.Add(item);
}
listView.EndUpdate();
Esto es mejor, pero todavía un orden de magnitud demasiado lento. Vamos creación separada de ListViewItems de añadir ListViewItems, por lo que encontrar el verdadero culpable:
Intento 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()
El verdadero cuello de botella es la adición de los artículos. Vamos a tratar de convertirlo en AddRange
en lugar de un intento foreach
4:2,182 ms
listView.BeginUpdate();
listView.Items.AddRange(items.ToArray());
listView.EndUpdate();
un poco mejor. Vamos a estar seguros de que el cuello de botella no está en la ToArray()
Intento 5:2,132 ms
ListViewItem[] arr = items.ToArray();
stopwatch.Start();
listView.BeginUpdate();
listView.Items.AddRange(arr);
listView.EndUpdate();
stopwatch.Stop();
La limitación parece ser la adición de elementos a la vista de lista. Tal vez la otra sobrecarga del AddRange
, donde se añade un ListView.ListViewItemCollection
en lugar de una matriz
Intento 6:2,141 ms
listView.BeginUpdate();
ListView.ListViewItemCollection lvic = new ListView.ListViewItemCollection(listView);
lvic.AddRange(arr);
listView.EndUpdate();
Bueno, eso no es mejor.
Ahora es el momento para estirar:
Paso 1 - asegurarse de que ninguna columna se establece en "auto-anchura":
Comprobar
Paso 2 - asegurarse de que el ListView no está tratando de ordenar los elementos cada vez que la tuya:
Comprobar
Paso 3 - Haz stackoverflow:
Comprobar
Nota: Obviamente, esto no es ListView en modo virtual; ya que no puede/no puede "agregar" elementos a una vista de lista virtual (configura el VirtualListSize
). Afortunadamente, mi pregunta no es acerca de una vista de lista en modo virtual.
¿Hay algo que me falta que pueda explicar que la adición de elementos a la lista vista sea tan lenta?
Bono Chatter
sé la clase ListView Windows puede hacerlo mejor, porque puedo escribir código que lo hace en 394 ms
:
ListView1.Items.BeginUpdate;
for i := 1 to 53709 do
ListView1.Items.Add();
ListView1.Items.EndUpdate;
que cuando se compara con el equivalente C# código 1,349 ms
:
listView.BeginUpdate();
for (int i = 1; i <= 53709; i++)
listView.Items.Add(new ListViewItem());
listView.EndUpdate();
es un orden de magnitud más rápido.
¿Qué propiedad de WinForms ListView wrapper me falta?
Nota al margen: si utiliza Casillas de verificación, debe establecer el estado verificado antes de agregarlo a ListView. Inicializar los estados comprobados http://blogs.msdn.com/b/hippietim/archive/2006/03/20/556007.aspx –
Tengo que preguntar: ¿por qué agregas ESO muchos elementos? –
Gran pregunta Ian. ¿Has visto este blog sobre el tema? http://www.virtualdub.org/blog/pivot/entry.php?id=273 –