SORU
25 Ocak 2012, ÇARŞAMBA


Nasıl bir liste Görünümü öğeler ekleme hız için?

Win bir liste Görünümü için bin (örn: 53,709) birkaç parça daha ekliyorum.

Deneme 1: 8**

foreach (Object o in list)
{
   ListViewItem item = new ListViewItem();
   RefreshListViewItem(item, o);
   listView.Items.Add(item);
}

Bu çok kötü bir şekilde çalışır. Bariz ilk düzeltme BeginUpdate/EndUpdate aramak.

Girişimi 2: 3,106 ms

listView.BeginUpdate();
foreach (Object o in list)
{
   ListViewItem item = new ListViewItem();
   RefreshListViewItem(item, o);
   listView.Items.Add(item);
}
listView.EndUpdate();

Bu daha iyi, ama hala büyüklük çok yavaş bir emirdir. Ekleyerek ListViewİtems gelelim ayrı yaratılış ListViewİtems, gerçek suçluyu bulana kadar:

Girişimi 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()

Gerçek darboğaz öğeler ekliyor. Hadi AddRange yerine foreach bir dönüştürme deneyin

Girişimi 4:2,182 ms

listView.BeginUpdate();
listView.Items.AddRange(items.ToArray());
listView.EndUpdate();

Biraz daha iyi. Bu darboğaz ToArray() içinde olmadığından emin olalım

Girişim 5:2,132 ms

ListViewItem[] arr = items.ToArray();

stopwatch.Start();

listView.BeginUpdate();
listView.Items.AddRange(arr);
listView.EndUpdate();

stopwatch.Stop();

Sınırlama liste görünümü öğeler ekleme gibi görünüyor. Biz ekliyoruz AddRange, diğer bir aşırı yüklenme ListView.ListViewItemCollection bir dizi yerine belki

Girişim 6:2,141 ms

listView.BeginUpdate();
ListView.ListViewItemCollection lvic = new ListView.ListViewItemCollection(listView);
lvic.AddRange(arr);
listView.EndUpdate();

Ama bu hiç iyi değil.

Şimdi dinlenme zamanı

  • Adım 1- hiçbir sütun için ayarlanmış olduğundan emin olun< . em ^"otomatik genişlik":

    enter image description here

    Kontrol edin

  • Adım 2- Liste Görünümü öğesi eklemek her zaman sıralamak için çalışıyor olmadığından emin olun:

    enter image description here

    Kontrol edin

  • Adım 3- Stackoverflow sor:

    enter image description here

    Kontrol edin

Not:Belli ki bu liste Görünümü musun beri sanal modunda değil; mi/olamaz "" sanal liste görünümü öğeleri (VirtualListSize ayarlayın). Ekle Neyse benim sorum sanal modunda bir liste görünümü hakkında değil.

Liste görünümü çok yavaş olduğu için öğeler eklemek için hesap olabilir kaçırdığım bir şey var mı?


Bonus Gevezelik

Windows Liste Görünümü sınıf 394 ms bu kod yazabilirim, çünkü daha iyi, biliyorum:

ListView1.Items.BeginUpdate;
for i := 1 to 53709 do
   ListView1.Items.Add();
ListView1.Items.EndUpdate;

eşdeğer C ile kıyaslandığında# kod 1,349 ms:

listView.BeginUpdate();
for (int i = 1; i <= 53709; i  )
   listView.Items.Add(new ListViewItem());
listView.EndUpdate();

büyüklükte bir sipariş daha hızlı.

Ne özelliği Win Liste Görünümü sarıcı mi kaçırdım?

CEVAP
26 Ocak 2012, PERŞEMBE


Ve performans 4 faktör tarafından yavaş yapabilir birkaç şey fark ettim görüntüleyin kadar görmüş olduğunuz liste için kod: kaynak bir göz attım

Liste Görünümü.cs, ListViewItemsCollection.AddRange benim denetim başladığım yer olan ListViewNativeItemCollection.AddRange çağırır

ListViewNativeItemCollection.AddRange (satır: 18120) iki geçer tüm koleksiyonu değerleri, toplamak tüm kontrol öğeleri başka bir 'geri' onlardan sonra InsertItems denir (ikisi de korunan bir kontrol karşı owner.IsHandleCreated sahibi olmak ListView) çağrı BeginUpdate.

ListView.InsertItems (satır: 12952), ilk olarak, tüm liste başka bir geçiş var o zaman ArrayList arayın.AddRange (muhtemelen bir geçiş daha var) ondan sonra da bir geçiş olarak adlandırılır. Lider

ListView.InsertItems (satır: 12952), Ara () EndUpdate) başka bir geçitten nereye eklenir HashTable Debug.Assert(!listItemsTable.ContainsKey(ItemId)) yavaş daha fazla hata ayıklama modu. Eğer tanıtıcı oluşturulan değil, ArrayList, listItemsArray if (IsHandleCreated), sonra bir çağrı için öğeleri ekler

ListView.InsertItemsNative (satır: 3848) son aslında doğal görünümü eklenir nereye listesinde geçiyor. Debug.Assert(this.Items.Contains(li) ayrıca hata ayıklama modunda performans yavaşlatacaktır.

Bu öğelerin tüm liste boyunca ekstra paslar var .net hiçbir şey yerli liste görünümü öğeleri ekleme ulaşmadan kontrol. Geçer bazı eğer oluşturulmadan önce tanıtıcı öğeleri ekleyebilirsiniz, size biraz zaman kazandırabilir böylece yaratılan Ele karşı çekler tarafından korunuyor. OnHandleCreated yöntemi listItemsArray aramalar InsertItemsNative doğrudan tüm ekstra gürültü patırtı olmadan alır.

source reference Kendin indirip bir göz atabilirsiniz, belki bir şeyler kaçırdım.

İşte bir blog yazısı ve diğer şeylerin ListView performance, tartışıyor. Daha hızlı işlemek önce öğeleri eklemek için oluşturulan, ancak denetim işlenirken bir bedel ödeyecek ettiğini göstermektedir. Belki işleme iyileştirmeleri açıklamalarda belirtilen uygulama ve kolu önce öğeleri oluşturulur ekleyerek her iki dünyanın en iyi olsun.

Edit: çeşitli şekillerde bu hipotezi Test edilmiş ve kolu oluşturmadan önce öğeleri ekleme suuuper hızlı iken, kolu oluşturmak için gittiğinde katlanarak daha yavaş olur. Bu kolu oluşturmak için kandırmaya çalışıyorum ile oynadım, bir şekilde tüm ekstra geçirir geçmeden İnsertİtemsNative diyebilir o zaman, ama ne yazık ki bertaraf oldum. Tek şey istiyorum acaba mümkün olabilir, oluşturmak için Win32 görüntüsünde bir c projesi, eşyaları öğeleri ve kullanım çengel için yakalama Kuyruk ileti ile gönderilen Liste Görünümü oluştururken onun başa geçmesi ve tekrar başvuru için win 32 Liste Görünümü yerine, yeni bir pencere.. ama kim bilir ne gibi yan etkiler olur... win 32 guru için ne yapmalıyım konuş hakkında çılgın bir fikir :)

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • ElChakotay Andrich

    ElChakotay A

    10 EKİM 2013
  • Kindness

    Kindness

    23 Ocak 2006
  • Max Lee

    Max Lee

    18 AĞUSTOS 2006