Почему TStringList имеет BeginUpdate и EndUpdate? - PullRequest
13 голосов
/ 05 февраля 2012

Я понимаю, что использование BeginUpdate и EndUpdate на элементах управления VCL, таких как TListBox, ускоряет процесс заполнения элемента управления элементами, поскольку предотвращает перерисовку элемента управления до тех пор, пока не будет вызван 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 выполняется в памяти, а не визуально.Должен ли я в любом случае использовать BeginUpdate и EndUpdate для TStringList, хорошо ли это делать?

Мне глупо спрашивать об этом, но почему в TStringList есть процедуры BeginUpdate и EndUpdate?

IЯ думаю, что я мог ответить на свой вопрос здесь, так или иначе, я хотел бы услышать ваши взгляды.

Спасибо:)

Ответы [ 3 ]

21 голосов
/ 05 февраля 2012

BeginUpdate запрещает события OnChanging и OnChange списка строк.В зависимости от того, что подключено, это может значительно ускорить процесс.

В вашем примере BeginUpdate / EndUpdate не имеет большого значения.Использование экземпляра TStringlist и присвоение его представлению списка является вполне допустимым подходом.

10 голосов
/ 05 февраля 2012

BeginUpdate и EndUpdate введены в абстрактный базовый класс TStrings. Так что TStringList наследует эту возможность, хотя она не особенно полезна. Тем не менее, это, конечно, полезно для многих других TStrings потомков.

Помните, что многие другие TStrings потомки имеют частную реализацию. Например, объект TStrings, связанный с TListBox, является частным для раздела реализации модуля StdCtrls. Элемент управления TListBox предоставляет список элементов как TStrings, поэтому для доступности BeginUpdate и EndUpdate их необходимо объявить в абстрактном базовом классе.

На мой взгляд, вы можете безопасно игнорировать эти методы при работе с объектом, который, как вы знаете, TStringList.

Теперь, что касается кода, который заполняет представление списка, я не вижу никакого смысла в использовании промежуточного TStringList. Я бы просто заполнил представление списка напрямую и использовал бы BeginUpdate / EndUpdate в представлении списка Items. Если у вас все еще есть проблемы с производительностью в вашем представлении списка, то решением является виртуальное представление списка.

2 голосов
/ 06 февраля 2012

Это просто реализация шаблона блокировки , как объяснено здесь .

Это позволяет вам temporarily lock аспект класса, избегая ненужных уведомлений.

То же самое, что вы можете найти в DB.TDataSet.DisableControls и DB.TDataSet.EnableControls .

...