Why does TStringList have BeginUpdate and EndUpdate?
-
22-04-2021 - |
Question
I understand that using BeginUpdate and EndUpdate on VCL controls such as TListBox speeds up the process of populating the control with Items as it prevents the control from being repainted, until EndUpdate is called.
Example:
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;
The above will have a delay because the Listbox is allowed to be repainted, but the delay can be shorted by preventing repainting like so:
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;
Now I tested this using a 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;
It seems that regardless if the TStringList uses BegindUpdate and EndUpdate, the list is populated at approximately the same speed..
Are they really needed though as the TStringList is performed in memory and not visually. Should I use BeginUpdate and EndUpdate on a TStringList anyway, is it good practice to do this?
I feel silly for asking this but why does the TStringList have the procedures BeginUpdate and EndUpdate?
I think I may have answered my own question here, either way I would like to hear your views.
Thanks :)
Solution
The BeginUpdate
inhibits the OnChanging
and OnChange
events of the stringlist. Depending on what is connected, it can speed up things significantly.
In your example the BeginUpdate/EndUpdate doesn't make much difference. Using a TStringlist instance and assigning it to the listview is quite a valid approach.
OTHER TIPS
BeginUpdate
and EndUpdate
are introduced in the abstract base class TStrings
. So TStringList
inherits this capability even though it's not particularly useful. However, it is of course useful for many other TStrings
descendants.
Remember that many other TStrings
descendants have private implementation. For example, the TStrings
object associated with a TListBox
is private to the implementation section of the StdCtrls
unit. The TListBox
control exposes item list as TStrings
and so to make BeginUpdate
and EndUpdate
available, they need to be declared in the abstract base class.
In my view you can safely ignore these methods when working with an object that you know to be TStringList
.
Now, regarding the code that populates the list view, I see no point whatsoever in using an intermediate TStringList
. I would simply populate the list view directly and make use of BeginUpdate
/EndUpdate
on the list view Items
. If you still have performance problems with your list view then the solution is a virtual list view.
It's just an implementation of the lock pattern as explained here.
It allows you to you temporarily lock
an aspect of the class, avoiding unneeded notifications.
Quite the same as you can find in DB.TDataSet.DisableControls and DB.TDataSet.EnableControls.