为什么TStringList有BeginUpdate和EndUpdate?

时间:2012-02-05 16:24:04

标签: delphi library-design

据我所知,在TLIBox等VCL控件上使用BeginUpdate和EndUpdate会加快使用Items填充控件的过程,因为它会阻止控件重新绘制,直到调用EndUpdate为止。

示例:

procedure TForm1.AddItems;
var
  i: Integer;
begin
  Screen.Cursor := crHourGlass;
  try
    for i := 0 to 5000 do
    begin
      ListBox1.Items.Add('Item' + IntToStr(i));
    end;
  finally
    Screen.Cursor := crDefault;
  end;
end;

以上会有延迟,因为允许重新绘制列表框,但可以通过防止重新绘制来缩短延迟:

procedure TForm1.AddItems;
var
  i: Integer;
begin
  Screen.Cursor := crHourGlass;
  try
    ListBox1.Items.BeginUpdate;
    try
      for i := 0 to 5000 do
      begin
        ListBox1.Items.Add('Item' + IntToStr(i));
      end;
    finally
      ListBox1.Items.EndUpdate;
    end;
  finally
    Screen.Cursor := crDefault;
  end;
end;

现在我使用TStringList测试了这个:

procedure TForm1.AddItems;
var
  SL: TStringList;
  i: Integer;
begin
  SL := TStringList.Create;
  try
    Screen.Cursor := crHourGlass;
    try
      SL.BeginUpdate;
      try
        for i := 0 to 5000 do
        begin
          SL.Add('Item' + IntToStr(i));
        end;
      finally
        SL.EndUpdate;
      end;

      ListBox1.Items.Assign(SL);
    finally
      Screen.Cursor := crDefault;
    end;
  finally
    SL.Free;
  end;
end;

似乎无论TStringList是否使用BegindUpdate和EndUpdate,列表都以大致相同的速度填充..

它们是否真的需要,因为TStringList在内存中执行而不是在视觉上执行。无论如何我应该在TStringList上使用BeginUpdate和EndUpdate,这样做是不错的做法?

我对此问题感到愚蠢,但为什么TStringList有程序BeginUpdate和EndUpdate?

我想我可能已经在这里回答了我自己的问题,无论我想听听你的意见。

谢谢:)

3 个答案:

答案 0 :(得分:20)

BeginUpdate会禁止字符串列表中的OnChangingOnChange事件。根据连接的内容,它可以显着加快速度。

在您的示例中,BeginUpdate / EndUpdate没有太大区别。使用TStringlist实例并将其分配给listview是一种非常有效的方法。

答案 1 :(得分:10)

BeginUpdateEndUpdate在抽象基类TStrings中引入。所以TStringList继承了这个功能,即使它不是特别有用。但是,它对许多其他TStrings后代当然有用。

请记住,许多其他TStrings后代都有私有实现。例如,与TStrings关联的TListBox对象对StdCtrls单元的实现部分是私有的。 TListBox控件将项列表公开为TStrings,因此要使BeginUpdateEndUpdate可用,需要在抽象基类中声明它们。

在我看来,在处理您知道为TStringList的对象时,可以放心地忽略这些方法。

现在,关于填充列表视图的代码,我认为使用中间TStringList没有任何意义。我只是直接填充列表视图,并在列表视图BeginUpdate上使用EndUpdate / Items。如果列表视图仍然存在性能问题,则解决方案是虚拟列表视图。

答案 2 :(得分:2)

这只是锁定模式的实现,如here所述。

它允许您temporarily lock类的一个方面,避免不必要的通知。

DB.TDataSet.DisableControls DB.TDataSet.EnableControls 中可以找到的相同。