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 :)

Was it helpful?

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top