Подтвердить что ты не робот

Почему TStringList имеет BeginUpdate и EndUpdate?

Я понимаю, что с помощью 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;

Вышеупомянутая будет иметь задержку, потому что Listbox разрешено перекрашивать, но задержка может быть закорочена, предотвращая перерисовку следующим образом:

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?

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

Спасибо:)

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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

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

Ответ 3

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

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

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