delphi – 获取总CPU使用率的百分比

前端之家收集整理的这篇文章主要介绍了delphi – 获取总CPU使用率的百分比前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图将总cpu使用率的百分比变为label1.Caption

搜索并找到了这些:

>没用 – http://www.vbforums.com/showthread.php?345723-DELPHI-Get-CPU-Usage
>不是我需要的 – http://delphi.cjcsoft.net/viewthread.php?tid=42837

>还发现了一堆关于计算每个进程的使用量的解决方案,但这不是我想要的,我只想要总cpu使用率
喜欢这个小部件:

这就是我正在做的事情:

我相信有一种简单的方法就像我们使用RAM一样.

GlobalMemoryStatus(RamStats);
 Label1.Caption := Format('RAM: %d %%',[RamStats.dwMemoryLoad]);

解决方法

我找到了一篇文章,determine-cpu-usage-of-current-process-c-and-c,关于如何获得当前进程的cpu使用率.

现在,我们需要通过为每个正在运行的进程累加cpu使用百分比来计算总cpu使用率百分比:

function GetTotalcpuUsagePct(): Double;
var
  ProcessID: TProcessID;
  RunningProcessIDs : TArray<TProcessID>;
begin
  Result := 0.0;
  RunningProcessIDs := GetRunningProcessIDs;

  DeleteNonExistingProcessIDsFromCache(RunningProcessIDs);

  for ProcessID in RunningProcessIDs do
    Result := Result + GetProcesscpuUsagePct( ProcessID );

end;

在获得运行进程ID之后,我们开始调用
DeleteNonExistingProcessIDsFromCache用于清理缓存,该缓存保存GetProcesscpuUsagePct中所需的先前cpu使用时间:自上次查询以来已停止的每个进程都从此缓存中删除.

GetProcesscpuUsagePct是核心,它是determine-cpu-usage-of-current-process-c-and-c的转换.此函数需要使用ProcessID从cpu Usage Cache LatestProcesscpuUsageCache(单元中的全局)检索先前的读取.
注意,建议不要每隔200毫秒调用GetToalcpuUsagecpu,因为它可能会给出错误的结果.

function GetProcesscpuUsagePct(ProcessID: TProcessID): Double;
  function SubtractFileTime(FileTime1: TFileTIme; FileTime2: TFileTIme): TFileTIme;
  begin
    Result := TFileTIme(Int64(FileTime1) - Int64(FileTime2));
  end;

var
  ProcesscpuUsage: TProcesscpuUsage;
  ProcessHandle: THandle;
  SystemTimes: TSystemTimesRec;
  SystemDiffTimes: TSystemTimesRec;
  ProcessDiffTimes: TProcessTimesRec;
  ProcessTimes: TProcessTimesRec;

  SystemTimesIdleTime: TFileTime;
  ProcessTimesCreationTime: TFileTime;
  ProcessTimesExitTime: TFileTime;
begin
  Result := 0.0;

  LatestProcesscpuUsageCache.TryGetValue(ProcessID,ProcesscpuUsage);
  if ProcesscpuUsage = nil then
  begin
    ProcesscpuUsage := TProcesscpuUsage.Create;
    LatestProcesscpuUsageCache.Add(ProcessID,ProcesscpuUsage);
  end;
  // method from:
  // http://www.philosophicalgeek.com/2009/01/03/determine-cpu-usage-of-current-process-c-and-c/
  ProcessHandle := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ,False,ProcessID);
  if ProcessHandle <> 0 then
  begin
    try
      if GetSystemTimes(SystemTimesIdleTime,SystemTimes.KernelTime,SystemTimes.UserTime) then
      begin
        SystemDiffTimes.KernelTime := SubtractFileTime(SystemTimes.KernelTime,ProcesscpuUsage.LastSystemTimes.KernelTime);
        SystemDiffTimes.UserTime := SubtractFileTime(SystemTimes.UserTime,ProcesscpuUsage.LastSystemTimes.UserTime);
        ProcesscpuUsage.LastSystemTimes := SystemTimes;
        if GetProcessTimes(ProcessHandle,ProcessTimesCreationTime,ProcessTimesExitTime,ProcessTimes.KernelTime,ProcessTimes.UserTime) then
        begin
          ProcessDiffTimes.KernelTime := SubtractFileTime(ProcessTimes.KernelTime,ProcesscpuUsage.LastProcessTimes.KernelTime);
          ProcessDiffTimes.UserTime := SubtractFileTime(ProcessTimes.UserTime,ProcesscpuUsage.LastProcessTimes.UserTime);
          ProcesscpuUsage.LastProcessTimes := ProcessTimes;
          if (Int64(SystemDiffTimes.KernelTime) + Int64(SystemDiffTimes.UserTime)) > 0 then
            Result := (Int64(ProcessDiffTimes.KernelTime) + Int64(ProcessDiffTimes.UserTime)) / (Int64(SystemDiffTimes.KernelTime) + Int64(SystemDiffTimes.UserTime)) * 100;
        end;
      end;
    finally
      CloseHandle(ProcessHandle);
    end;
  end;
end;

以下是Windows 7上结果的屏幕截图.

完整的单位清单:

unit uTotalcpuUsagePct;

interface

  function GetTotalcpuUsagePct : Double;

implementation

uses
  SysUtils,DateUtils,Windows,PsAPI,TlHelp32,ShellAPI,Generics.Collections;

type
  TProcessID = DWORD;

  TSystemTimesRec = record
    KernelTime: TFileTIme;
    UserTime: TFileTIme;
  end;

  TProcessTimesRec = record
    KernelTime: TFileTIme;
    UserTime: TFileTIme;
  end;

  TProcesscpuUsage = class
    LastSystemTimes: TSystemTimesRec;
    LastProcessTimes: TProcessTimesRec;
    ProcesscpuusagePercentage: Double;
  end;

  TProcesscpuUsageList = TObjectDictionary<TProcessID,TProcesscpuUsage>;

var
  LatestProcesscpuUsageCache : TProcesscpuUsageList;
  LastQueryTime : TDateTime;

(* -------------------------------------------------------------------------- *)

function GetRunningProcessIDs: TArray<TProcessID>;
var
  SnapProcHandle: THandle;
  ProcEntry: TProcessEntry32;
  NextProc: Boolean;
begin
  SnapProcHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
  if SnapProcHandle <> INVALID_HANDLE_VALUE then
  begin
    try
      ProcEntry.dwSize := SizeOf(ProcEntry);
      NextProc := Process32First(SnapProcHandle,ProcEntry);
      while NextProc do
      begin
        SetLength(Result,Length(Result) + 1);
        Result[Length(Result) - 1] := ProcEntry.th32ProcessID;
        NextProc := Process32Next(SnapProcHandle,ProcEntry);
      end;
    finally
      CloseHandle(SnapProcHandle);
    end;
    TArray.Sort<TProcessID>(Result);
  end;
end;

(* -------------------------------------------------------------------------- *)

function GetProcesscpuUsagePct(ProcessID: TProcessID): Double;
  function SubtractFileTime(FileTime1: TFileTIme; FileTime2: TFileTIme): TFileTIme;
  begin
    Result := TFileTIme(Int64(FileTime1) - Int64(FileTime2));
  end;

var
  ProcesscpuUsage: TProcesscpuUsage;
  ProcessHandle: THandle;
  SystemTimes: TSystemTimesRec;
  SystemDiffTimes: TSystemTimesRec;
  ProcessDiffTimes: TProcessTimesRec;
  ProcessTimes: TProcessTimesRec;

  SystemTimesIdleTime: TFileTime;
  ProcessTimesCreationTime: TFileTime;
  ProcessTimesExitTime: TFileTime;
begin
  Result := 0.0;

  LatestProcesscpuUsageCache.TryGetValue(ProcessID,ProcesscpuUsage.LastProcessTimes.UserTime);
          ProcesscpuUsage.LastProcessTimes := ProcessTimes;
          if (Int64(SystemDiffTimes.KernelTime) + Int64(SystemDiffTimes.UserTime)) > 0 then
            Result := (Int64(ProcessDiffTimes.KernelTime) + Int64(ProcessDiffTimes.UserTime)) / (Int64(SystemDiffTimes.KernelTime) + Int64(SystemDiffTimes.UserTime)) * 100;
        end;
      end;
    finally
      CloseHandle(ProcessHandle);
    end;
  end;
end;

(* -------------------------------------------------------------------------- *)

procedure DeleteNonExistingProcessIDsFromCache(const RunningProcessIDs : TArray<TProcessID>);
var
  FoundKeyIdx: Integer;
  Keys: TArray<TProcessID>;
  n: Integer;
begin
  Keys := LatestProcesscpuUsageCache.Keys.ToArray;
  for n := Low(Keys) to High(Keys) do
  begin
    if not TArray.BinarySearch<TProcessID>(RunningProcessIDs,Keys[n],FoundKeyIdx) then
      LatestProcesscpuUsageCache.Remove(Keys[n]);
  end;
end;

(* -------------------------------------------------------------------------- *)

function GetTotalcpuUsagePct(): Double;
var
  ProcessID: TProcessID;
  RunningProcessIDs : TArray<TProcessID>;
begin
  Result := 0.0;
  RunningProcessIDs := GetRunningProcessIDs;

  DeleteNonExistingProcessIDsFromCache(RunningProcessIDs);

  for ProcessID in RunningProcessIDs do
    Result := Result + GetProcesscpuUsagePct( ProcessID );

end;

(* -------------------------------------------------------------------------- *)

initialization
  LatestProcesscpuUsageCache := TProcesscpuUsageList.Create( [ doOwnsValues ] );
  // init:
  GetTotalcpuUsagePct;
finalization
  LatestProcesscpuUsageCache.Free;
end.

测试代码

单位Unit1;

interface

uses
  Vcl.Forms,System.SysUtils,Vcl.Controls,Vcl.StdCtrls,System.Classes,Vcl.ExtCtrls,uTotalcpuUsagePct;

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    Label1: TLabel;
    procedure Timer1Timer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  // start cpu load thread
  TThread.CreateAnonymousThread(
    procedure
    begin
      while True do
      begin
      end;
    end).Start;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  TotalcpuusagePercentage: Double;
begin
  TotalcpuusagePercentage := GetTotalcpuUsagePct();
  Label1.Caption := 'Total cpu: ' + IntToStr(Round(TotalcpuusagePercentage)) + '%';
end;

end.

猜你在找的Delphi相关文章