据我所知,在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?
我想我可能已经在这里回答了我自己的问题,无论我想听听你的意见。
谢谢:)
答案 0 :(得分:20)
BeginUpdate
会禁止字符串列表中的OnChanging
和OnChange
事件。根据连接的内容,它可以显着加快速度。
在您的示例中,BeginUpdate / EndUpdate没有太大区别。使用TStringlist实例并将其分配给listview是一种非常有效的方法。
答案 1 :(得分:10)
BeginUpdate
和EndUpdate
在抽象基类TStrings
中引入。所以TStringList
继承了这个功能,即使它不是特别有用。但是,它对许多其他TStrings
后代当然有用。
请记住,许多其他TStrings
后代都有私有实现。例如,与TStrings
关联的TListBox
对象对StdCtrls
单元的实现部分是私有的。 TListBox
控件将项列表公开为TStrings
,因此要使BeginUpdate
和EndUpdate
可用,需要在抽象基类中声明它们。
在我看来,在处理您知道为TStringList
的对象时,可以放心地忽略这些方法。
现在,关于填充列表视图的代码,我认为使用中间TStringList
没有任何意义。我只是直接填充列表视图,并在列表视图BeginUpdate
上使用EndUpdate
/ Items
。如果列表视图仍然存在性能问题,则解决方案是虚拟列表视图。
答案 2 :(得分:2)
这只是锁定模式的实现,如here所述。
它允许您temporarily lock
类的一个方面,避免不必要的通知。
在 DB.TDataSet.DisableControls 和 DB.TDataSet.EnableControls 中可以找到的相同。