寻找Win32 API函数,C ++或Delphi示例代码,它告诉我线程的CPU使用率(百分比和/或总CPU时间)(而不是进程的总和)。我有线程ID。
我知道Sysinternals Process Explorer可以显示这些信息,但我需要在我的程序中提供这些信息。
答案 0 :(得分:23)
您必须使用这些函数来获取每个线程和进程的cpu使用情况。
GetThreadTimes (检索指定线程的计时信息。)
GetProcessTimes(检索指定进程的计时信息。)
GetSystemTime(检索当前系统日期和时间。系统时间以协调世界时UTC表示)
这是来自Dobb博士Win32 Performance Measurement Options
的优秀文章再见。
答案 1 :(得分:10)
您使用特定WMI来电时可以使用您所引用的数据。您可以查询Win32_Process以获取各种特定于进程的信息,并查询Win32_PerfFormattedData_PerfProc_Process以获取线程数,并给出线程的句柄(我相信您正在寻找),您可以查询Win32_PerfRawData_PerfProc_Thread以获取百分比处理器使用时间。
有一个library available for Delphi为大多数WMI查询提供包装器,但是需要进行一些实验才能获得您要查找的确切查询。查询语法非常像sql,例如在我的系统上返回threadid 8的处理器时间百分比,因为进程id 4是:
SELECT PercentProcessorTime FROM Win32_PerfRawData_PerfProc_Thread
WHERE IdProcess=4 and IdThread=8
大多数提供有关正在运行的进程的统计信息的程序现在都使用WMI来查询此信息。
答案 2 :(得分:7)
重要的是要知道在某些情况下,线程的执行时间可能毫无价值。
对于多核系统,每个线程的执行时间通常每15毫秒更新一次,因此如果线程在此时间之前完成其任务,则将重置运行时。
更多细节可以在链接上获得:
GetThreadTimes function and I was surprised by the result!
和
Why GetThreadTimes is wrong
答案 3 :(得分: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;
答案 4 :(得分:4)
使用“GetThreadTimes”?如果您测量调用“GetThreadTimes”并存储前一个用户和/或内核时间之间的时间,那么您就知道自上次检查以来该线程已经有多长时间了。您还知道平均时间已经过了多少时间,因此您可以计算出使用了多少CPU时间。最好(出于计时器分辨率的原因)每隔一秒左右进行一次检查,并计算出其平均CPU使用率。
答案 5 :(得分:1)
Here 是一个简单的WMI查询包装器。借助它,您可以调用它来获取数据:
getWmiQueryResult(L"SELECT PercentProcessorTime FROM Win32_PerfRawData_PerfProc_Thread WHERE IdProcess=4 and IdThread=8", L"PercentProcessorTime ");
另外,您可能需要查看Win32_PerfRawData_PerfProc_Thread文档,了解您可以获取的其他属性。
答案 6 :(得分:1)
此示例使用GetProcessTimes()
,但可以轻松修改为使用GetThreadTimes()
。
假设将ISO C的clock()
除以CLOCKS_PER_SEC
,可为您提供经过的CPU秒数。但是,Visual Studio 2019网页显示:
时钟功能可显示自从 进程启动期间的CRT初始化。请注意,此功能确实 不严格符合ISO C,ISO C将净CPU时间指定为 返回值。
所以,这是我的替身。在Windows 7 / Visual Studio 2017中,CLOCKS_PER_SEC
为1000,而GetProcessTimes()
仅具有毫秒精度,因此返回clock_t
而不是double
不会造成精度损失。
clock_t AKClock() {
#ifdef WIN32
FILETIME ftimeCreate, ftimeExit, ftimeKernel, ftimeUser;
SYSTEMTIME stimeKernel, stimeUser;
if ( ! GetProcessTimes( GetCurrentProcess(), &ftimeCreate, &ftimeExit,
&ftimeKernel, &ftimeUser ) ||
! FileTimeToSystemTime( &ftimeKernel, &stimeKernel ) ||
! FileTimeToSystemTime( &ftimeUser, &stimeUser ) ) {
char szError[ 1024 ];
MyLoggingFunction( "AKClock() failed; returning -1: %s",
AKGetLastError( szError, sizeof( szError ) ) );
return (clock_t) -1.0;
}
return (clock_t)
( ( stimeKernel.wHour * 3600.0 +
stimeKernel.wMinute * 60.0 +
stimeKernel.wSecond +
stimeKernel.wMilliseconds / 1000.0 +
stimeUser.wHour * 3600.0 +
stimeUser.wMinute * 60.0 +
stimeUser.wSecond +
stimeUser.wMilliseconds / 1000.0 ) * CLOCKS_PER_SEC );
#else
return clock();
#endif
}
为了完整起见,这是AKGetLastError():
void AKstrncpy( char *pszDest, const char *pszSrc, const size_t sDest ) {
strncpy( pszDest, pszSrc, sDest );
pszDest[ sDest - 1 ] = '\0';
}
char* AKGetLastError( char* szBuf, int iBufSize ) {
DWORD errorMessageID = GetLastError();
char* pszError = NULL;
size_t sizeBuf;
if( errorMessageID == 0 ) {
AKstrncpy( szBuf, "(no error)", iBufSize );
return szBuf;
}
sizeBuf = FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errorMessageID, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
(LPSTR) &pszError, 0, NULL );
AKstrncpy( szBuf, pszError, iBufSize );
LocalFree( pszError );
int iLen = strlen( szBuf );
if ( strcmp( szBuf + iLen - 2, "\r\n" ) == 0 )
szBuf[ iLen - 2 ] = '\0';
return szBuf;
}