可能你不知道的 CPU 资源杀手

问题的提出:

如果你没有用过 TAction,或许你不该说你会 DelphiTAction 大大简化了界面逻辑的关联,加速了项目的开发。不过我在程序中大量使用 TAction 时,无意发现这样一个问题:如果程序的某个窗体里有超过100TAction,在运行这个程序时,只要不停的在该窗体上快速移动鼠标,CPU 占用率会猛增到 30% 左右。

 

为什么会有如此高的 CPU 占用?

使用 Spy++ 调试后发现,一旦鼠标快速在窗体上移动,程序会频繁发送 WM_UPDATE 消息。进一步调试后发现,TContainedAction.Update() TActionManager 频繁调用。正如帮助文档中所写:当应用程序处于空闲状态时,所有的 TxxxxAction.OnUpdate 事件会被触发。由于空闲状态频繁改变,因此 OnUpdate 也就被频繁触发,这个正是造成不当 CPU 占用的真正原因。

 
解决方案

如果你的程序中没有使用到 TxxxxAction.OnUpdate,那么你可以屏蔽 TActionManager 去查询并触发 TxxxxAction.OnUpdate。具体实现代码如下:

uses
 FastcodePatch
{http://fastcode.sourceforge.net/};

procedure TContainedActionUpdateStub;
asm
 call TContainedAction.Update;
end;

type
 TContainedActionPatch =
class(TContainedAction)
 
public
   
function Update: Boolean; override;
 
end;

function TContainedActionPatch.Update: Boolean;
begin
 Result := False;
end;

function DisableTActionOnUpdate(ActnList: TActionList): Boolean;
var
 I: Integer;
begin
 Result := True;
 
for I := 0to ActnList.ActionCount - 1do
   
if Assigned(ActnList.Actions[I].OnUpdate) then
   
begin
      Result := False;
      Break;
   
end;

 
if Result then
 
begin
    FastcodeAddressPatch(
      FastcodeGetAddress(@TContainedActionUpdateStub),
      @TContainedActionPatch.Update);
 
end;
end;


这段代码的最佳运行位置是在你程序窗体的OnCreate() 事件中。当然如果你希望彻底解决这个问题你可以修改ActnList.pas 中的TContainedAction.Update,或者提交申请让CodeGear 来改进这个问题。

 
总结

本文展示了过多使用TxxxxAction 组件可能会造成应用程序过高的CPU 占用问题。并且提供了补丁代码来解决这个问题。尽管我手上没有最新版本的 Delphi,但是估计这个问题是不会被 CodeGear 修正的。

 
 

没有更多推荐了,返回首页

私密
私密原因:
请选择设置私密原因
  • 广告
  • 抄袭
  • 版权
  • 政治
  • 色情
  • 无意义
  • 其他
其他原因:
120
出错啦
系统繁忙,请稍后再试

关闭