此问题"How to get the CPU Usage in C#?"显示了获取.NET中计算机当前CPU使用率(%)的一些方法。
由于CPU使用率频繁波动,我认为当前的CPU使用率通常不是计算机繁忙程度的良好指标(例如,用于调度或负载平衡目的)。有没有一种有效的方法来获得最后x分钟的平均CPU使用率,例如最后5分钟?
我正在考虑可以由负载平衡或调度模块调用的方法GetAverageCpuUsage(int period)。
答案 0 :(得分:5)
实际上,这正是PerformanceCounter来自the 2nd most upvoted answer的另一个问题,它们的测量时间超过1秒。
它给出的百分比是计数器上最后NextValue()
的cpu集合的平均百分比。因此,如果您想要在过去5分钟内获得平均cpu,请每5分钟只调用一次NextValue()
。
Here is a good article解释如何使用效果计数器。
答案 1 :(得分:1)
上面的答案给出了计算CPU使用率的一个很好的例子。但我想指出一些不正确的东西并被误导。 SubtractTimes函数需要略有不同。
private UInt64 SubtractTimes(ComTypes.FILETIME a, ComTypes.FILETIME b)
{
UInt64 aInt = ((UInt64)(a.dwHighDateTime << 32)) | (UInt32)a.dwLowDateTime;
UInt64 bInt = ((UInt64)(b.dwHighDateTime << 32)) | (UInt32)b.dwLowDateTime;
return aInt - bInt;
}
注意lowDateTime的UINT32。这是因为,至少在C#中,comtype.FILETIME结构将DWORD转换为int32,因此如果该值大于MAX签名的Int,则会看到一个负值,这绝不应该是这种情况。如果你把它直接投射到&#34; UINT64&#34; type,在内部用于保留符号,首先将其转换为Int64,然后转换为UInt64,以便您看到不正确的值。相反,您希望将lowDateTime转换为Uint32类型以消除负号,然后转换为UInt64(这将自动发生,因为它是|操作的一部分)。同样应该适用于dwHighDateTime conponent,但这很好,因为它通常不应超过MaxInt(好吧,这又取决于你的用例)。
答案 2 :(得分:0)
尝试类似:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using ComTypes = System.Runtime.InteropServices.ComTypes;
using System.Threading;
using System.Diagnostics;
namespace example1
{
public class CpuUsage
{
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool GetSystemTimes(
out ComTypes.FILETIME lpIdleTime,
out ComTypes.FILETIME lpKernelTime,
out ComTypes.FILETIME lpUserTime
);
ComTypes.FILETIME _prevSysKernel;
ComTypes.FILETIME _prevSysUser;
TimeSpan _prevProcTotal;
Int16 _cpuUsage;
DateTime _lastRun;
long _runCount;
public CpuUsage()
{
_cpuUsage = -1;
_lastRun = DateTime.MinValue;
_prevSysUser.dwHighDateTime = _prevSysUser.dwLowDateTime = 0;
_prevSysKernel.dwHighDateTime = _prevSysKernel.dwLowDateTime = 0;
_prevProcTotal = TimeSpan.MinValue;
_runCount = 0;
}
public short GetUsage()
{
short cpuCopy = _cpuUsage;
if (Interlocked.Increment(ref _runCount) == 1)
{
if (!EnoughTimePassed)
{
Interlocked.Decrement(ref _runCount);
return cpuCopy;
}
ComTypes.FILETIME sysIdle, sysKernel, sysUser;
TimeSpan procTime;
Process process = Process.GetCurrentProcess();
procTime = process.TotalProcessorTime;
if (!GetSystemTimes(out sysIdle, out sysKernel, out sysUser))
{
Interlocked.Decrement(ref _runCount);
return cpuCopy;
}
if (!IsFirstRun)
{
UInt64 sysKernelDiff = SubtractTimes(sysKernel, _prevSysKernel);
UInt64 sysUserDiff = SubtractTimes(sysUser, _prevSysUser);
UInt64 sysTotal = sysKernelDiff + sysUserDiff;
Int64 procTotal = procTime.Ticks - _prevProcTotal.Ticks;
if (sysTotal > 0)
{
_cpuUsage = (short)((100.0 * procTotal) / sysTotal);
}
}
_prevProcTotal = procTime;
_prevSysKernel = sysKernel;
_prevSysUser = sysUser;
_lastRun = DateTime.Now;
cpuCopy = _cpuUsage;
}
Interlocked.Decrement(ref _runCount);
return cpuCopy;
}
private UInt64 SubtractTimes(ComTypes.FILETIME a, ComTypes.FILETIME b)
{
UInt64 aInt = ((UInt64)(a.dwHighDateTime << 32)) | (UInt64)a.dwLowDateTime;
UInt64 bInt = ((UInt64)(b.dwHighDateTime << 32)) | (UInt64)b.dwLowDateTime;
return aInt - bInt;
}
private bool EnoughTimePassed
{
get
{
const int minimumElapsedMS = 250;
TimeSpan sinceLast = DateTime.Now - _lastRun;
return sinceLast.TotalMilliseconds > minimumElapsedMS;
}
}
private bool IsFirstRun
{
get
{
return (_lastRun == DateTime.MinValue);
}
}
}
}
在您的代码中使用它之后:
CpuUsage _cu = new CpuUsage();
string cpuUsage = _cu.GetUsage();
帮助了某些事情