Как определить причину, по которой основной поток не отвечает с Omni Thread Library?

Платформа: Delphi с VirtualTreeView SVN 5.1.0 и OmniThreadLibrary 3 SVN & Delphi XE2

Первоначально я думал, что проблема была VirtualTreeView. Мне нужно добавлять узел в VST каждые 1 с или менее. Но, похоже, рано или поздно частота процессора достигнет 50% или более, пока все приложение не будет полностью реагировать.

  var FAbort:Boolean;
  .....

  procedure TrmMain.btnAddNodeClick(Sender: TObject);
    begin
      while not FAbort do
      begin
        VstMain.RootNodeCount:= VstMain.RootNodeCount + 1;
        Sleep(10);
        Application.ProcessMessages;
      end;
    end;

Кто-нибудь может помочь? ТИА!

РЕДАКТИРОВАТЬ: Кажется, проблема исходит от OTL. При использовании приведенного выше кода минимизируйте нагрузку на ЦП приложения менее чем на 1%, даже измените время ожидания 10 мс на 1 мс.

Но приведенный ниже код воспроизводит проблему, которая беспокоит меня.

procedure TForm1.btn5Click(Sender: TObject);
var
  I: Integer;
begin
  for I := 0 to 1 do
    CreateTask(
      procedure(const Task: IOmniTask)
      begin
        while not FAbort do
        begin
          Task.Comm.Send(1, 0);
          Sleep(10);
        end;
      end).OnMessage(
      procedure(const Task: IOmniTaskControl; const Msg: TOmniMessage)
      begin
        vst1.AddChild(nil);
      end).Run;
end;

PS: Во избежание перехода к стандартному размеру очереди OTL 1000 у меня действительно есть блокировка в каждом потоке, которая ожидает завершения добавления узла перед следующей операцией Task.Comm.Send.

PPS: 10 мс здесь просто для быстрого воспроизведения проблемы, а не в реальной ситуации. Так что не спрашивайте почему?

Итак, вывод таков: просто не добавляйте слишком много узлов на одном узле, если вам нужно периодически обновлять этот узел, чем больше узлов, тем больше процессорного времени для их обновления.

2 ответа

Решение

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

VirtualTreeView - это визуальный контроль. Людям не нужно видеть обновление дерева в реальном времени, тратится впустую больше, чем 3 раза в секунду. Так что не делай этого.

Вместо этого обновите модель (объекты, классы), установите флаг уведомления, а затем (из TTimer) выполните асинхронное одноразовое обновление VirtualStringTree.RootNodeCount, которое происходит максимум 3 раза в секунду. (Более чем одна установка этого флага обновления каждые 333 мсек приводит к минимальному периоду ожидания 333 мсек, пока он фактически не обновится.) Это мой произвольный пользовательский интерфейс "быстрее, чем этот, и это просто мерцание и отток, и никакой пользы" константа,

Разработчики Delphi столкнулись с этим с помощью VirtualTreeView, я знаю, потому что я зарегистрировал ошибку QC. Если вы сделали достаточно сообщений "OutputDebugString" в Delphi 2009, среда IDE перестает отвечать на запросы. Зачем? Потому что они сделали то, что ты делаешь. Не делай этого. Я не говорю, что пользовательский щелчок должен вызвать 333 мс ожидания, прежде чем экран обновится. Я говорю, что некоторый процесс, который генерирует древовидный контент непрерывно, должен только уведомлять "контроллер представления" дерева об изменениях максимум 3 раза в секунду.

Если вы добавите узлы с помощью функции AddChild(), все может получиться лучше, чем доступ к свойству RootNodeCount.

Например, что-то вроде:

procedure TMyForm.OnTimer( Sender: TObject );
var
  Node: PVirtualNode;
begin
  Node := MyTree.AddChild( nil );
  // fill in details with GetNodeData( Node );

end;

Еще лучше: используйте таймер и попробуйте добавить несколько элементов за интервал времени:

procedure TMyForm.OnTimer( Sender: TObject );
begin
  AddToList( ... );
end;

procedure TMyForm.OnTimer( Sender: TObject );
var
  Node: PVirtualNode;
  Item: <Some iterator>;
begin
  MyTree.BeginUpdate();
  try
    for Item in <somelist> do begin
      Node := MyTree.AddChild( nil );
      // fill in details with GetNodeData( Node );
    end;
  finally
    MyTree.EndUpdate();
  end; 
end;
Другие вопросы по тегам