【问题标题】:Enumerating ListView.SelectedIndices is slow on huge ListView在巨大的 ListView 上枚举 ListView.SelectedIndices 很慢
【发布时间】:2011-04-13 19:00:51
【问题描述】:

我有一个带有 VirtualMode = true 的 ListView 和大量项目(目前约为 800,000)。

我的目标是在每次选定项目更改时对所有选定项目中的一个字段求​​和。

问题是枚举所有所选项目需要很长时间选择大量项目。例如,枚举 800,000 个选定项需要 1 秒。这意味着对于每个单一的选择更改,用户必须等待整整 1 秒,然后 GUI 才会再次响应,这很烦人。

我不明白为什么枚举选定的项目这么慢,在一个简单的数组中枚举相同数量的项目什么都不用。

如何加快 ListView 中选定项目的枚举过程?

【问题讨论】:

  • 您是否考虑过捕获指示给定项目被选中或未选中的消息,并使用该数据直接更新您的运行总数?

标签: c# .net winforms performance listview


【解决方案1】:

这取决于您的操作方式,您可能想用一些代码详细说明一下,但是您不能在选择每个项目时保持运行总计,而不是每次选择时都遍历整个列表是造出来的?

【讨论】:

  • 代码很简单:foreach (int index in listView1.SelectedIndices);没什么特别的。列表视图的选择更改事件并没有准确地告诉我发生了什么变化,所以每次我都需要重新枚举整个选定的项目。
  • 如果您没有从当前控件中获取信息,您可能必须对其进行子类化并在其中添加计数方法,无论是“更改”还是访问基础数据。您如何访问要汇总的数据,它不在 SelectedIndicies 中,因此那里的重定向可能会占用 CPU 时间。
【解决方案2】:

WinForms ListView 的一个问题是它构建在 Win32Control 之上,因此对 ListView 的每个请求都必须从托管代码传递到无人代码,然后再返回。

var myArray = new int[myListView.SelectedIndices.Count];
myListView.SelectedIndices.CopyTo(myArray) 

可能会更快,值得一试

您是否考虑过使用 WPF?您可以为列表编写一个 WPF 控件,然后将其托管在 WinForm 表单中。

【讨论】:

  • 谢谢,但是 CopyTo() 方法的性能与常规枚举完全相同。 WPF 现在不适合我,因为我需要支持 Windows 2000。
【解决方案3】:

底层控制是主要问题。只需要一定的时间来检查每个项目并确定它是否是下一个选定的行。

通过直接向控件发送消息,可以使枚举过程大约快一倍:

[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);

private void button1_Click(object sender, EventArgs e)
{
    Stopwatch sw = new Stopwatch();

    sw.Start();
    IntPtr h = this.listView1.Handle;
    int j = 0;
    int i = SendMessage(h, 0x100C, -1, 2);
    while (i > -1) {
        j++;
        i = SendMessage(h, 0x100C, i, 2);
    }

    sw.Stop();
    this.toolStripStatusLabel1.Text = String.Format("Timed: {0} items in {1}ms",
        j, sw.ElapsedMilliseconds);
}

在我的机器上,这将迭代所选项目所需的时间减半。但这个过程永远不会一蹴而就。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-06
    • 2015-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-03
    • 1970-01-01
    相关资源
    最近更新 更多