2

プラットフォーム: VirtualTreeView SVN 5.1.0 & OmniThreadLibrary 3 SVN & Delphi XE2 を搭載した Delphi

もともと問題はVirtualTreeViewだと思っていました。1 秒以下ごとに VST にノードを追加する必要があります。しかし、アプリケーション全体が完全に応答しなくなるまで、CPU レートはすぐに 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から来ているようです。上記のコードを使用する場合、アプリケーションを最小化して CPU を常に 1% 未満にし、10ms のスリープを 1ms に変更します。

しかし、以下のコードは私を悩ませている問題を再現します。

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 ミリ秒は、実際の状況ではなく、問題をすばやく再現するためのものです。では、わざわざ理由を尋ねないでください。

OK、結論は次のとおりです。このノードを定期的に更新する必要がある場合は、単一ノードにノードを追加しすぎないでください。ノードが多いほど、それらを更新するためのCPU時間が長くなります。

4

2 に答える 2

2

私の見解では、基礎となるモデルが変更されたときに、特に毎回ではなく、ビューを同期的に更新するべきではありません。

VirtualTreeViewは視覚的なコントロールです。人間はリアルタイムでツリーの更新を確認する必要はありません。1秒あたり3倍以上が無駄になります。だからそれをしないでください。

代わりに、モデル(オブジェクト、クラス)を更新し、通知フラグを設定してから、(TTimerから)VirtualStringTree.RootNodeCountの非同期SINGLE更新を実行します。これは、最大で1秒あたり3回発生します。(333ミリ秒ごとにこの更新フラグを複数設定すると、実際に更新されるまでの最小待機時間は333ミリ秒になります。)これは、私の任意のユーザーインターフェイスです。 。

Delphi自身の開発者は、VirtualTreeViewでこれに遭遇しました。これは、関連するQCバグをログに記録したためです。Delphi 2009で十分な「OutputDebugString」メッセージを実行すると、IDEが応答しなくなります。なんで?彼らはあなたがしていることをしたからです。しないでください。ユーザーがクリックすると、画面が更新されるまで333ミリ秒待機する必要があると言っているのではありません。ツリーコンテンツを継続的に生成している一部のプロセスは、ツリーの「ビューコントローラ」に1秒間に最大3回の変更のみを通知する必要があると言っています。

于 2013-01-11T19:51:35.097 に答える
1

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;
于 2013-01-10T06:53:37.260 に答える