問題說明:
為了維護程序的結構,我在程序中大量使用Action。其優點大家都知道,我可以讓MenuItem對應某個Action,同時讓工具欄上的Toolbutton也對於相同的Action。這樣我只需要對Action進行編程,而MenuItemToolButton都可以相關到這個事件。
不過我發現了一個非常奇怪的問題。當我在程序中創建了4個工具欄。然後初始化程序時動態創建ToolButton(大約40個),同時把他們都關聯到不同的Action。(整個程序還只是一個空殼子,所有的Action裡面還沒有放入代碼)我在主窗體上面的空白處(非工具欄區域)移動鼠標,用任務管理器監視。CPU占用率達30%左右(其他程序都關閉了)。如果我動態創建ToolButton的時候先關聯Action,然後再取消管理Action,CPU占有率就下降到10%左右。
解決思路:
發現是由於在出發 WM_UPDATE 事件的時候,TActionManager會詢問所有 TAction,是否需要響應 OnUpdate 事件。而這個 WM_UPDATE 觸發的頻率相當頻繁,可想而知,不斷對所有 TAction 進行詢問,需要占用大量的 CPU 時間。在實際運用過程中,這個 OnUpdate 事件幾乎不被用到。因此設計了如下的補丁程序。
function TContainedAction.Update: Boolean;
begin {
Result := (ActionList <> nil) and ActionList.UpdateAction(Self) or
Application.UpdateAction(Self) or inherited Update or
(SendAppMessage(CM_ACTIONUPDATE, 0, Longint(Self)) = 1);
}
// ---------------------------------------------------------
// OnUpdate may cause serious performance problem.
// CPU usage is always at about 20-30% (AthlonXP 2100+)
// ---------------------------------------------------------
Result := False; // patched by 5291 2004-05-15
end;
把修改後的 ActnList.pas 拷貝到你的應用程序路徑之下然後編譯該程序。這個文件修改了原先的Update方法。你的程序可以直接使用新的 ActnList.dcu,你可以用它覆蓋原先的組件。