Estoy agregando algunos miles (por ejemplo, 53,709) elementos a un ListView de WinForms.
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 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 sigue siendo un orden de magnitud demasiado lento. Separemos la creación de ListViewItems de la adición de ListViewItems, para que encontremos al culpable real:
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 agregar los elementos. Intentemos convertirlo en en AddRange
lugar de unforeach
Intento 4: 2,182 ms
listView.BeginUpdate();
listView.Items.AddRange(items.ToArray());
listView.EndUpdate();
Un poco mejor. Asegurémonos de que el cuello de botella no esté en elToArray()
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 agregar elementos a la vista de lista. Tal vez la otra sobrecarga de AddRange
, donde agregamos un en ListView.ListViewItemCollection
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 de estirar:
Paso 1 : asegúrese de que ninguna columna esté configurada en "ancho automático" :
Cheque
Paso 2 : asegúrese de que ListView no intente ordenar los elementos cada vez que agregue uno:
Cheque
Paso 3 - Pregunte a stackoverflow:
Cheque
Nota: Obviamente, este ListView no está en modo virtual; ya que no puede "agregar" elementos a una vista de lista virtual (establece el VirtualListSize
). Afortunadamente, mi pregunta no se trata de una vista de lista en modo virtual.
¿Hay algo que me falte que pueda explicar el hecho de que agregar elementos a la vista de lista sea tan lento?
Chatter adicional
Sé que la clase ListView de Windows puede funcionar 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 en comparación con el código C # equivalente 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 del contenedor de WinForms ListView me falta?