我要每3秒取一次设置好的几个进程的CPU点用率,网上找了一个例子,取一个进程得到的CPU利用率结果正常(和任务管理器里显示的数据一样),可是同时取多个进程的CPU率得到的结果都是错误的,这是什么原因?同时执行这个函数会有什么共享冲突吗?
int GetCpuUsage(DWORD pID) //传入进程ID,返回CPU利用率
{
int cpuusage;
PVOID pProcInfo = NULL;
DWORD dwInfoSize = 0x20000;
PPROCESSINFO pProcessInfo;
DWORD dwWorkingSet;
long ( __stdcall *NtQuerySystemInformation )( DWORD, PVOID, DWORD, DWORD ); static __int64 LastTotalProcessCPUUsage = 0;
static __int64 LastCurrentProcessCPUUsage = 0;
int CurrentDelta;
int TotalDelta;
__int64 TotalProcessCPUUsage = 0;
__int64 CurrentProcessCPUUsage = 0;
/////////////////////////////////
pProcInfo = (PVOID)(new byte[dwInfoSize]);
NtQuerySystemInformation = (long(__stdcall*)(DWORD,PVOID,DWORD,DWORD))
GetProcAddress( GetModuleHandle( "ntdll.dll" ),"NtQuerySystemInformation" );
NtQuerySystemInformation(5,pProcInfo,dwInfoSize,0);
pProcessInfo = (PPROCESSINFO)pProcInfo;
do
{
TotalProcessCPUUsage += (__int64)pProcessInfo->KernelTime.QuadPart + (__int64)pProcessInfo->UserTime.QuadPart;
if(pProcessInfo->dwProcessID == pID)
{
dwWorkingSet = pProcessInfo->dwWorkingSet;
CurrentProcessCPUUsage += (__int64)pProcessInfo->KernelTime.QuadPart + (__int64)pProcessInfo->UserTime.QuadPart;
}
/////////
if(pProcessInfo->dwOffset == 0)
{
break;
}
pProcessInfo = (PPROCESSINFO)((byte*)pProcessInfo + pProcessInfo->dwOffset);
}
while(true);
TotalDelta = TotalProcessCPUUsage - LastTotalProcessCPUUsage;
CurrentDelta = CurrentProcessCPUUsage - LastCurrentProcessCPUUsage;
if(TotalDelta != 0)
cpuusage = 100 * CurrentDelta / TotalDelta;
//this->Caption = "CPU = " + IntToStr(100 * CurrentDelta / TotalDelta) +
//"Memory = "+ IntToStr(dwWorkingSet / 1024) " K";
LastTotalProcessCPUUsage = TotalProcessCPUUsage;
LastCurrentProcessCPUUsage = CurrentProcessCPUUsage;
delete[] pProcInfo;
return cpuusage;}

解决方案 »

  1.   

    你是計算總cpu佔用率和前一次cpu佔用率的差值?
      

  2.   

    对于单核的cpu,某一时刻,必然只有一个线程在执行,
    当然也就只有一个进程可以有cpu占用率吧。
    猜的。
      

  3.   

    // 得到当前进程的CPU占用率
    class GetCPUPercentage
    ...{
      private:
        CRITICAL_SECTION cs;  // 供多线程同步的临界区变量
        HANDLE hd;    // 空闲进程的句柄
        DWORD t1;     // 时间戳
        int percent;  // 最近一次计算的CPU占用率    __int64 oldp;
        __int64 FileTimeToInt64(const FILETIME& time);
        int GetTime(__int64& proc);  // 得到进程占用的CPU时间
      public:
        GetCPUPercentage();
        ~GetCPUPercentage();    int Get();  // 得到CPU占用率
    };GetCPUPercentage::GetCPUPercentage()
    ...{
      InitializeCriticalSection(&cs);  // 初始化线程临界区变量  percent = 0;   // 初始的占用率  DWORD pid = GetCurrentProcessId();   // 得到当前进程id
      hd  = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);  // 通过id得到进程的句柄
      if( hd==NULL )...{
         return;
      }  // 得到初始时刻的值
      GetTime(oldp);
      t1 = GetTickCount();
    }GetCPUPercentage::~GetCPUPercentage()
    ...{
      if( hd!=NULL )...{
         CloseHandle(hd);
      }
      DeleteCriticalSection(&cs);
    }// 时间格式转换
    __int64 GetCPUPercentage::FileTimeToInt64(const FILETIME& time)
    ...{
      ULARGE_INTEGER tt;
      tt.LowPart = time.dwLowDateTime;
      tt.HighPart = time.dwHighDateTime;
      return(tt.QuadPart);
    }// 得到进程占用的CPU时间 
    int GetCPUPercentage::GetTime(__int64& proc)
    ...{
      FILETIME create;
      FILETIME exit;
      FILETIME ker;  // 内核占用时间
      FILETIME user; // 用户占用时间
      FILETIME now;
      if( !GetProcessTimes(hd, &create, &exit, &ker, &user) )...{
         return(-1);
      }  proc = (FileTimeToInt64(ker) + FileTimeToInt64(user))/10000;
      return(0);
    }// 进行换算
    int GetCPUPercentage::Get()
    ...{
      if( hd==NULL )
         return(0);  EnterCriticalSection(&cs);
        DWORD t2 = GetTickCount();
        DWORD dt = t2 - t1;
        if( dt>139 )...{  // 毫秒数。用一个比较少的时间片作为计算单位,这个值可修改
           __int64 proc;
           GetTime(proc);       percent = ((proc-oldp)*100)/dt;       t1 = t2;
           oldp = proc;
        }
      LeaveCriticalSection(&cs);
      return(percent);
    }// 定义一个全局变量
    GetCPUPercentage _cpu;// 下面是用C++Bulider写的测试例子:
    // --------------------------
    // 在用一个时钟不停地显示当前的CPU占用率
    void __fastcall TForm1::Timer1Timer(TObject *Sender)
    ...{
      Label1->Caption = _cpu.Get();
    }//---------------------------------------------------------------------------
    // 再弄个按钮
    LRESULT WINAPI TestThread(LONG lParam)
    ...{
      int n = lParam;
      for(int i=0 ;i<n; i++)...{
         Form1->Label2->Caption = i;
         Sleep(12);
      }
      return(0);
    }
    // 点击这个按钮会创建一些线程来把CPU整的繁忙些
    void __fastcall TForm1::Button1Click(TObject *Sender)
    ...{
      int n = atoi(Edit1->Text.c_str());
      DWORD dwThreadid;
      CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)TestThread,
                    (void*)n, 0, &dwThreadid);
    }文章出处:http://www.diybl.com/course/3_program/c++/cppsl/2008516/117032.html
      

  4.   


       HQUERY hQuery;
        PDH_STATUS pdhStatus = PdhOpenQuery(0, 0, &hQuery);
        HCOUNTER pCounterHandle;
        PDH_FMT_COUNTERVALUE fmtValue;
        DWORD dwctrType;
        pdhStatus = PdhAddCounter(hQuery, _TEXT("\\Process(进程名)\\% Processor Time"), 0, &pCounterHandle);
        pdhStatus = PdhCollectQueryData(hQuery);
        Sleep(1000);
        pdhStatus = PdhCollectQueryData(hQuery);
        pdhStatus = PdhGetFormattedCounterValue(pCounterHandle, PDH_FMT_DOUBLE, &dwctrType, &fmtValue);
        pdhStatus = PdhCloseQuery(hQuery);
    fmtValue.doubleValue