平台:Delphi与VirtualTreeView SVN 5.1.0& OmniThreadLibrary 3 SVN&德尔福XE2
最初我认为问题是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;
任何人都可以提供帮助? TIA!
编辑:似乎问题来自 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:这里的10ms只是为了快速重现问题,而不是在实际情况下。所以不要问为什么?
好的,结论是:如果你需要定期更新这个节点,就不要在单个节点上添加太多节点,节点越多,更新它们的CPU时间就越多。
答案 0 :(得分:2)
在我看来,当基础模型发生变化时,不应同步更新视图,尤其是不是每次都更新。
VirtualTreeView是一个可视化控件。人类不需要实时查看树更新,每秒浪费超过3倍。所以不要这样做。
相反,更新模型(对象,类),设置通知标志,然后(从TTimer),执行VirtualStringTree.RootNodeCount的异步SINGLE更新,最多每秒3次。 (每个333毫秒的这个更新标志的多个设置导致最小等待时间为333毫秒,直到它实际更新为止。)这是我的任意用户界面“比这更快,它只是闪烁和流失,并且没有任何用处”常数
Delphi自己的开发人员使用VirtualTreeView遇到了这个问题,我知道因为我记录了涉及的QC错误。如果您在Delphi 2009中执行了足够的“OutputDebugString”消息,IDE将变得无响应。为什么?因为他们做了你正在做的事情。不要这样做。我并不是说用户点击会导致屏幕刷新前等待333毫秒。我说一些连续生成树内容的进程应该只通知树的“视图控制器”每秒更改3次,最大值。
答案 1 :(得分: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;