如何用Delphi 11获取自身进程的实时CPU使用率(与任务管理器一致)
Delphi 11 获取自身进程CPU使用率(与任务管理器一致)
要实现和Windows任务管理器中“CPU”列完全一致的进程CPU使用率,需要通过两次采样进程CPU时间与系统总CPU时间,计算两者的差值比例,同时考虑多核CPU的总处理能力。以下是具体实现:
核心思路
任务管理器的进程CPU使用率计算公式为:进程CPU使用率 = (当前进程CPU时间 - 上次进程CPU时间) / (当前系统总CPU时间 - 上次系统总CPU时间) * 100
其中系统总CPU时间是所有CPU核心的用户态+内核态时间总和(排除空闲时间),这样计算出的数值会和任务管理器完全匹配(包括多核场景下超过100%的情况)。
完整代码实现
unit ProcessCPUUsage; interface uses Winapi.Windows, System.SysUtils; type TProcessCPUUsage = class private FLastProcessUserTime: Int64; FLastProcessKernelTime: Int64; FLastSystemIdleTime: Int64; FLastSystemKernelTime: Int64; FLastSystemUserTime: Int64; FProcessHandle: THandle; function GetSystemTotalTime: Int64; public constructor Create; destructor Destroy; override; function GetCPUUsage: Double; end; implementation constructor TProcessCPUUsage.Create; begin inherited; // 获取当前进程句柄(系统自动管理,无需手动关闭) FProcessHandle := GetCurrentProcess; // 初始化首次采样数据 GetProcessTimes(FProcessHandle, nil, nil, PLargeInteger(@FLastProcessKernelTime), PLargeInteger(@FLastProcessUserTime)); GetSystemTimes(PLargeInteger(@FLastSystemIdleTime), PLargeInteger(@FLastSystemKernelTime), PLargeInteger(@FLastSystemUserTime)); end; destructor TProcessCPUUsage.Destroy; begin inherited; end; function TProcessCPUUsage.GetSystemTotalTime: Int64; begin // 系统总CPU时间 = 用户态时间 + 内核态时间 - 空闲时间(空闲时间属于内核态的无效占用,需排除) Result := (FLastSystemUserTime + FLastSystemKernelTime) - FLastSystemIdleTime; end; function TProcessCPUUsage.GetCPUUsage: Double; var CurrentProcessUserTime, CurrentProcessKernelTime: Int64; CurrentSystemIdleTime, CurrentSystemKernelTime, CurrentSystemUserTime: Int64; ProcessTimeDiff, SystemTimeDiff: Int64; begin Result := 0; // 获取当前进程CPU时间 if not GetProcessTimes(FProcessHandle, nil, nil, PLargeInteger(@CurrentProcessKernelTime), PLargeInteger(@CurrentProcessUserTime)) then Exit; // 获取当前系统CPU时间 if not GetSystemTimes(PLargeInteger(@CurrentSystemIdleTime), PLargeInteger(@CurrentSystemKernelTime), PLargeInteger(@CurrentSystemUserTime)) then Exit; // 计算两次采样的时间差 ProcessTimeDiff := (CurrentProcessUserTime - FLastProcessUserTime) + (CurrentProcessKernelTime - FLastProcessKernelTime); SystemTimeDiff := ((CurrentSystemUserTime + CurrentSystemKernelTime) - CurrentSystemIdleTime) - GetSystemTotalTime; if SystemTimeDiff > 0 then Result := (ProcessTimeDiff / SystemTimeDiff) * 100; // 更新采样基准数据 FLastProcessUserTime := CurrentProcessUserTime; FLastProcessKernelTime := CurrentProcessKernelTime; FLastSystemIdleTime := CurrentSystemIdleTime; FLastSystemKernelTime := CurrentSystemKernelTime; FLastSystemUserTime := CurrentSystemUserTime; end; end.
使用示例
在窗体中添加一个TTimer(设置Interval为1000,即1秒刷新一次)和一个TLabel显示CPU使用率:
procedure TForm1.FormCreate(Sender: TObject); begin FCPUUsage := TProcessCPUUsage.Create; end; procedure TForm1.Timer1Timer(Sender: TObject); var Usage: Double; begin Usage := FCPUUsage.GetCPUUsage; Label1.Caption := Format('自身进程CPU使用率: %.1f%%', [Usage]); end; procedure TForm1.FormDestroy(Sender: TObject); begin FCPUUsage.Free; end;
注意事项
- 首次调用
GetCPUUsage会返回0,因为没有前一次采样数据作对比,第二次及以后调用才能得到有效数值。 - 定时器间隔建议设为1秒,和任务管理器默认刷新频率一致,数值会完全同步。
- 若需获取其他进程的CPU使用率,只需将
FProcessHandle替换为目标进程的句柄(通过OpenProcess获取)。
内容的提问来源于stack exchange,提问作者delphirules
相关产品推荐
相关产品推荐

