3

この質問「C# で CPU 使用率を取得する方法は?」.NET でコンピューターの現在の CPU 使用率 (%) を取得するいくつかの方法を示します。

CPU 使用率は非常に頻繁に変動するため、現在の CPU 使用率は、コンピューターがどれだけビジーか (スケジューリングや負荷分散の目的など) の適切な指標にはならないことが多いと思います。過去 x 分間、たとえば過去 5 分間の平均 CPU 使用率を取得する効率的な方法はありますか?

負荷分散モジュールまたはスケジューリング モジュールから呼び出すことができるメソッド GetAverageCpuUsage(int period) のようなものを考えています。

4

3 に答える 3

7

実際、これは、他の質問で2番目に賛成された回答のPerformanceCounterが行うこととまったく同じであり、1秒以上を測定しているだけです。

NextValue()それが与える%は、最後にカウンターで行われたCPUの平均%です。したがって、過去5分間の平均CPUが必要な場合は、NextValue()5分ごとに1回だけ呼び出してください。

これは、パフォーマンスカウンターの使用方法を説明する良い記事です。

于 2013-02-05T05:58:12.800 に答える
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 signed Int を超える場合、決してそうであってはならない負の値が表示されます。これを「UINT64」型に直接キャストすると、符号を保持するために内部的にこれが最初に Int64 に変換され、次に UInt64 に変換されるため、正しくない値が表示されます。代わりに、負の符号を取り除くために lowDateTime を Uint32 型にキャストしてから、UInt64 にキャストします (これは | 操作の一部であるため、自動的に行われます)。同じことが dwHighDateTime コンポーネントにも当てはまりますが、通常は MaxInt を超えてはならないので問題ありません (ユースケースによって異なります)。

于 2016-12-29T18:59:42.683 に答える
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();

何かに役立った

于 2013-04-19T14:08:34.903 に答える