简体   繁体   English

c# ListView.Items[i].remove 很慢

[英]c# ListView.Items[i].remove is very slow

It is my first time here and I am struggling to solve this issue.这是我第一次来这里,我正在努力解决这个问题。 I have this piece of code:我有这段代码:

try
{
    progressBar1.Maximum = lista.Items.Count;
    lista.BeginUpdate();

    for (int i = 0; lista.Items.Count > i; i++)

    //for (int i = lista.Items.Count - 1; -1 < i; i--)
    {
        if (lista.Items[i].SubItems[1].Text.ToLower().Contains(Text) == false)
        {                        
            lista.Items[i].Remove();                        
        }

        progressBar1.Value = progressBar1.Value + 1;
    }

    lista.EndUpdate();

    progressBar1.Value = 0;
}
catch (Exception errore)
{
    txt_info.Text = "" + errore.Message;
    progressBar1.Value = 0;
}

The method lista.items[i].remove is extremely slow. lista.items[i].remove方法非常慢。 lista is a ListView and I am working on a log file bigger than 50,000 lines. lista是一个ListView ,我正在处理一个大于 50,000 行的日志文件。 Is there anyway to speed up the process?有没有办法加快这个过程?

I would take a different approach and use LINQ, something like this :我会采用不同的方法并使用 LINQ,如下所示:

lista.Items = lista.Items.Where(x=>x.SubItems[1].Text.ToLower.Contains(Text)).AsParallel().ToList();

Basically, rebuilding the list once rather than trying to remove individual items over and over again.基本上,重建列表一次而不是试图一遍又一遍地删除单个项目。

The simplest option would be to use the list's own RemoveAll method .最简单的选择是使用列表自己的RemoveAll 方法

list.RemoveAll(x => !x.SubItems[1].Text.ToLower().Contains(Text))

PS聚苯乙烯

You might want to look for speed gains in the actual comparison.您可能希望在实际比较中寻找速度提升。 Using String.Compare is much faster if your requirement fits it.如果您的要求适合,使用String.Compare会快得多。 If you want to check for a sub-string, I would suggest using ToUpperInvariant for invariance related matters - it's designed to be faster .如果您想检查子字符串,我建议将ToUpperInvariant用于与不变性相关的问题 -它旨在更快

ListViewItem[] allElements = new ListViewItem[listView1.Items.Count];
listView1.Items.CopyTo(allElements, 0);
List < ListViewItem > list = allElements.ToList();
list.RemoveAll(item => item.SubItems[1].Text.ToLower().Contains(TextToFind) == false);
listView1.BeginUpdate();
listView1.Clear();
listView1.Items.AddRange(list.ToArray());
listView1.EndUpdate();

First Rule is never update list in for loop.第一条规则永远不会在 for 循环中更新列表。 Your logic will only run till half of the list.您的逻辑只会运行到列表的一半。 I guess that's not what you want.我想那不是你想要的。
I've seen that manipulating listview.items is very slow even after using BeginUpdate and EndUpdate.我已经看到,即使在使用 BeginUpdate 和 EndUpdate 之后,操作 listview.items 也非常慢。 Key is to do the manipulation outside (in list or so) and then re populate the list with AddRange (which is much faster than Add).关键是在外部(在列表中)进行操作,然后使用 AddRange 重新填充列表(这比 Add 快得多)。

You could stick it in a background worker and have it do this on it's own.你可以把它放在后台工作人员中,让它自己做。 Therefore your users could still use the program while this process is occuring.因此,在此过程发生时,您的用户仍然可以使用该程序。

If you remove an item in for loop, you should set the counter to 1 less so you won't miss one.如果你在 for 循环中删除一个项目,你应该将计数器设置为 1 少,这样你就不会错过一个。 Because you remove [i], [old i+1] becomes the [new i] (Items.Count decreases 1 also) and you will miss checking the [new i].因为您删除 [i],[旧 i+1] 变成 [新 i](Items.Count 也减少 1)并且您将错过检查 [new i]。

eg: ListView.Items.Remove[i];例如: ListView.Items.Remove[i]; i--;

Lists are slow to access dynamically and much better suited to iteration.列表的动态访问速度很慢,更适合迭代。 I would suggest manipulating the data outside of the listview (maybe by copying the rows you want to display into a temporary list one at a time as you iterate across the source collection) and then assigning to the listview at the end.我建议在列表视图之外操作数据(也许通过在遍历源集合时将要显示的行一次复制到一个临时列表中),然后在最后分配给列表视图。 This can be done on a different thread (to improve UI performance) and doesn't require expensive lookups.这可以在不同的线程上完成(以提高 UI 性能)并且不需要昂贵的查找。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM