【问题标题】:TListView performance issuesTListView 性能问题
【发布时间】:2010-08-13 08:06:12
【问题描述】:

我尝试使用TListView 组件来显示相当大的数据列表(例如 4000 行大),但创建列表非常慢 - 大约需要 2-3 秒,这使得 UI 变得迟钝和关闭无法使用。

我在BeginUpdate/EndUpdate 块内填充TListView.Items,只使用预分配的字符串 - 我的意思是:我构建了一个要存储的所有字符串的列表(这不会花费人工注意的时间),然后我把它们放在 TListView 中。

我希望在 vsReport 模式下显示 TListView 的内容,并带有几列。

代码如下所示:

MyList.Items.BeginUpdate;
for i := 0 to MyCount - 1 do
begin
  ListItem := MyList.Items.Add;
  ListItem.Caption := StrCaptions[i];
  ListItem.SubItems.Add(StrSubItems1[i]);
  ListItem.SubItems.Add(StrSubItems2[i]);
end;
MyList.Items.EndUpdate;

我在 TListView 组件的逻辑中是否遗漏了其他一些技巧?还是我应该忘记使用这个组件进行表演?

【问题讨论】:

  • 是 StrCaptions 等 TStringLists 吗?或者获取 Items[i] 需要一些时间吗?
  • @Gerry :它们是哑数组

标签: delphi vcl


【解决方案1】:

您可以在虚拟模式下使用列表视图。看看 virtuallistview.dpr 演示。

【讨论】:

    【解决方案2】:

    你可以试试Virtual Treeview 组件。它说“虚拟树视图非常快。添加一百万个节点只需 700 毫秒”

    【讨论】:

    • 我正在尝试重写一些使用 TListViews 编写的 UI 代码,并且无法再处理数据大小。我已经(成功地)将一些变成了 TVirtualTrees - 并且更新是即时的。不过,迁移到 TVirtualTrees 非常耗时,我想知道是否可以更快地迁移现有代码。
    【解决方案3】:

    使用单独的结构来保存您的数据。将 TListView 的 OwnerData 设置为 True。

    【讨论】:

      【解决方案4】:

      @4000 行我只得到约 700 毫秒 (D2009) 次。为了提高响应能力,您可以分离到其他线程或将脏 Application.ProcessMessages() 添加到循环中。

      使用此代码在 16 毫秒内生成的行数:

        MyCount := 4000;
      
        dw := GetTickCount();
        for i := 0 to MyCount - 1 do begin
          StrCaptions.Add('caption'+IntToStr(i));
          StrSubItems1.Add('sub1'+IntToStr(i));
          StrSubItems2.Add('sub2'+IntToStr(i));
        end;
        ShowMessageFmt('%u ms', [GetTickCount() - dw]);
      

      印有:

        MyList.Clear;
      
        dw := GetTickCount();
        MyList.Items.BeginUpdate;
        for i := 0 to MyCount - 1 do
        begin
          ListItem := MyList.Items.Add;
          ListItem.Caption := StrCaptions[i];
          ListItem.SubItems.Add(StrSubItems1[i]);
          ListItem.SubItems.Add(StrSubItems2[i]);
        end;
        MyList.Items.EndUpdate;
        ShowMessageFmt('%u ms', [GetTickCount() - dw]);
      

      编辑: 我将 Application.ProcessMessages() 插入到 print 中,但 为什么 性能保持不变

      【讨论】:

      • 我刚刚在 D6 中在一台 6 岁的 P4 上尝试过这个,只用了 600 毫秒。尝试使用 SortType = stText,并使用随机数作为标题。
      • 如果您需要测量短至 16 ms 的间隔,您不能依赖GetTickCount。请改用QueryPerformanceCounterQueryPerformanceFrequency。将计数器值除以频率得到以秒为单位的间隔。
      • 甚至可能是 {function RDTSC:Int64; asm dw 310Fh end;} 用于降低开销,但这里毫秒就足够了,因为 LeGEC 以秒为单位表示时间。
      • 你有没有想过他的栏目可能比你多?另外我强烈建议不要使用Application.ProcessMessages。问题在于,它可能会导致您的应用程序可能处于更改某些对象状态的进程的中间,只是被启动另一个进程中断,该进程现在可能询问处于不稳定状态的对象>.
      • 正是因为这个原因,人们应该在进入for之前禁用控件并在try...finally之后启用它们
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-13
      • 2022-01-04
      • 2019-09-20
      • 2010-09-05
      相关资源
      最近更新 更多