如何获取Windows上每个线程的CPU使用率(win32)

Dir*_*ler 19 c++ delphi winapi multithreading cpu-usage

寻找Win32 API函数,C++或Delphi示例代码,它告诉我线程的CPU使用率(百分比和/或总CPU时间)(而不是进程的总和).我有线程ID.

我知道Sysinternals Process Explorer可以显示这些信息,但我在程序中需要这些信息.

RRU*_*RUZ 23

您必须使用这些函数来获取每个线程和进程的cpu使用情况.

GetThreadTimes(检索指定线程的计时信息.)

GetProcessTimes(检索指定进程的计时信息.)

GetSystemTime(检索当前系统日期和时间.系统时间以协调世界时UTC表示)

这是Dobb博士的Win32性能测量选项的优秀文章

再见.


ska*_*adt 10

您使用特定的WMI调用可以获得您要引用的数据.您可以查询Win32_Process以获取各种特定于进程的信息,并查询Win32_PerfFormattedData_PerfProc_Process以获取线程计数,并给出一个线程句柄(我相信您正在寻找),您可以查询Win32_PerfRawData_PerfProc_Thread以获得所用处理器时间的百分比.

有一个可用于Delphi库,它为大多数WMI查询提供包装器,但是需要一些实验才能获得您想要的确切查询.查询语法非常像sql,例如在我的系统上返回threadid 8的处理器时间百分比,因为进程id 4是:

SELECT PercentProcessorTime FROM Win32_PerfRawData_PerfProc_Thread 
  WHERE IdProcess=4 and IdThread=8
Run Code Online (Sandbox Code Playgroud)

现在,大多数提供有关正在运行的进程的统计信息的程序都使用WMI来查询此信息.


lsa*_*mon 8

重要的是要知道在某些情况下,线程的执行时间可能毫无价值.对于多核系统,每个线程的执行时间通常每15毫秒更新一次,因此如果线程在此时间之前完成其任务,则将重置运行时.更多细节可以在链接上获得: GetThreadTimes函数,我对结果感到惊讶!
以及 为什么GetThreadTimes是错误的

  • 显然在Vista +中,您可以调用QueryThreadCycleTime以获得更高的准确性.http://stackoverflow.com/questions/5532046/c-getthreadtimes-but-with-a-better-resolution我的猜测是Vista + GetThreadTimes也更准确,但是TBD. (4认同)

Dir*_*ler 6

在RRUZ上面的回答的帮助下,我终于想出了Borland Delphi的代码:

const
  THREAD_TERMINATE                 = $0001;
  THREAD_SUSPEND_RESUME            = $0002;
  THREAD_GET_CONTEXT               = $0008;
  THREAD_SET_CONTEXT               = $0010;
  THREAD_SET_INFORMATION           = $0020;
  THREAD_QUERY_INFORMATION         = $0040;
  THREAD_SET_THREAD_TOKEN          = $0080;
  THREAD_IMPERSONATE               = $0100;
  THREAD_DIRECT_IMPERSONATION      = $0200;
  THREAD_SET_LIMITED_INFORMATION   = $0400;
  THREAD_QUERY_LIMITED_INFORMATION = $0800;
  THREAD_ALL_ACCESS                = STANDARD_RIGHTS_REQUIRED or SYNCHRONIZE or $03FF;

function OpenThread(dwDesiredAccess: DWord;
                    bInheritHandle: Bool;
                    dwThreadId: DWord): DWord; stdcall; external 'kernel32.dll';


procedure TForm1.Button1Click(Sender: TObject);
var iii:integer;
    handle:thandle;
    creationtime,exittime,kerneltime,usertime:filetime;
begin
  Handle:=OpenThread(THREAD_SET_INFORMATION or THREAD_QUERY_INFORMATION, False, windows.GetCurrentThreadId);
  if handle<>0 then
  begin
    getthreadtimes(Handle,creationtime,exittime,kerneltime,usertime);
    label1.caption:='Total time for Thread #'+inttostr(windows.GetCurrentThreadId)+': '+inttostr( (int64(kerneltime)+int64(usertime)) div 1000 )+' msec';
    CloseHandle(Handle);
  end;
end;
Run Code Online (Sandbox Code Playgroud)