C#でCPU使用率を取得する方法?


204

C#でアプリケーションの全体的な合計CPU使用率を取得したいと考えています。プロセスのプロパティを詳しく調べる方法はたくさんありますが、必要なのは、プロセスのCPU使用率と、TaskManagerで得られるような合計CPUだけです。

それ、どうやったら出来るの?



36
これは一体どういうことなのでしょうか?ばかげている。
Peter Moore

回答:


205

System.DiagnosticsPerformanceCounterクラスを使用できます。

このように初期化します:

PerformanceCounter cpuCounter;
PerformanceCounter ramCounter;

cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
ramCounter = new PerformanceCounter("Memory", "Available MBytes");

このように消費します:

public string getCurrentCpuUsage(){
            return cpuCounter.NextValue()+"%";
}

public string getAvailableRAM(){
            return ramCounter.NextValue()+"MB";
} 

80
いいですが、元のソースはここにあるようです:zamov.online.fr/EXHTML/CSharp/CSharp_927308.html
Matt Refghi

19
私が発見したことから、cpuCounter.NextValue()を2回使用する必要があり、その間はSleep(500)にする必要がありました
Angel.King.47

マットは正しいです。「return」キーワードを忘れるようなバグも含みます。
Mark At Ramp51

8
ええ、それはそのリンクからのコピーのように見えるので、オリジナルの参照用のリンクは素晴らしいスタイルだったでしょう。一方、ここで答えを提供することもCMSの優れているため、怠惰な開発者は同じ答えを見つけるためにGoogle全体を検索する必要がありません。:o)
BerggreenDK 2011

13
System.Threading.Thread.Sleepを間に呼び出して、.NextValueを2回呼び出す必要があります(1000ミリ秒で十分です)。これが必要な理由の詳細については、blogs.msdn.com / b / bclteam / archive / 2006/06/02 / 618156.aspxを参照してください。ただし、高レベルの概要では、値を計算するために2つのサンプルが必要です。これらの両方を取得する時間をOSに与える必要があります。
Cleggy

63

要求されたものより少し多いですが、追加のタイマーコードを使用して、CPU使用率が1分以上継続して90%以上かどうかを追跡して警告します。

public class Form1
{

    int totalHits = 0;

    public object getCPUCounter()
    {

        PerformanceCounter cpuCounter = new PerformanceCounter();
        cpuCounter.CategoryName = "Processor";
        cpuCounter.CounterName = "% Processor Time";
        cpuCounter.InstanceName = "_Total";

                     // will always start at 0
        dynamic firstValue = cpuCounter.NextValue();
        System.Threading.Thread.Sleep(1000);
                    // now matches task manager reading
        dynamic secondValue = cpuCounter.NextValue();

        return secondValue;

    }


    private void Timer1_Tick(Object sender, EventArgs e)
    {
        int cpuPercent = (int)getCPUCounter();
        if (cpuPercent >= 90)
        {
            totalHits = totalHits + 1;
            if (totalHits == 60)
            {
                Interaction.MsgBox("ALERT 90% usage for 1 minute");
                totalHits = 0;
            }                        
        }
        else
        {
            totalHits = 0;
        }
        Label1.Text = cpuPercent + " % CPU";
        //Label2.Text = getRAMCounter() + " RAM Free";
        Label3.Text = totalHits + " seconds over 20% usage";
    }
}

7
getRAMCounter()はどこにありますか?
ディーターB 14

1
cpuCounter.NextValueを返しますfloat。それで、なぜそれをaに割り当てるのdynamicですか?次に、それをなぜとして返すdynamicobjectですか?なぜ割り当てようとobjectするintラインでint cpuPercent = getCPUCounter()?(そのコードはコンパイルされません。)
Wyck

21

かなり複雑に思えたいくつかの異なるスレッドを読んでしばらく時間を費やした後、私はこれを思いつきました。SQLサーバーを監視したい8コアマシンに必要でした。以下のコードでは、「sqlservr」をappNameとして渡しました。

private static void RunTest(string appName)
{
    bool done = false;
    PerformanceCounter total_cpu = new PerformanceCounter("Process", "% Processor Time", "_Total");
    PerformanceCounter process_cpu = new PerformanceCounter("Process", "% Processor Time", appName);
    while (!done)
    {
        float t = total_cpu.NextValue();
        float p = process_cpu.NextValue();
        Console.WriteLine(String.Format("_Total = {0}  App = {1} {2}%\n", t, p, p / t * 100));
        System.Threading.Thread.Sleep(1000);
    }
}

8コアサーバーでSQLによって使用されているCPUの割合を正しく測定しているようです。


total_cpuはPerformanceCounter( "Processor")ではなくPerformanceCounter( "Processor")である必要があります。それ以外の場合は、100%*コア数を取得するだけです。
スティーブクック

3
どこdoneにtrue を設定しますか?私が何かを見落としたのでない限り、これは無限ループのようです:while(!done){...}
Manfred

@Manfredそれは確かに無限のループです
Jenny

16

大丈夫、わかった!ご協力いただきありがとうございます!

これを行うコードは次のとおりです。

private void button1_Click(object sender, EventArgs e)
{
    selectedServer = "JS000943";
    listBox1.Items.Add(GetProcessorIdleTime(selectedServer).ToString());
}

private static int GetProcessorIdleTime(string selectedServer)
{
    try
    {
        var searcher = new
           ManagementObjectSearcher
             (@"\\"+ selectedServer +@"\root\CIMV2",
              "SELECT * FROM Win32_PerfFormattedData_PerfOS_Processor WHERE Name=\"_Total\"");

        ManagementObjectCollection collection = searcher.Get();
        ManagementObject queryObj = collection.Cast<ManagementObject>().First();

        return Convert.ToInt32(queryObj["PercentIdleTime"]);
    }
    catch (ManagementException e)
    {
        MessageBox.Show("An error occurred while querying for WMI data: " + e.Message);
    }
    return -1;
}

変数selectedServerの代わりにサーバー名の取得を追加した方が優れていました。this.string computername = Environment.GetEnvironmentVariable( "computername");のように
デイブ

9

WMIを使用して、CPUのパーセンテージ情報を取得できます。適切な権限があれば、リモートコンピュータにログインすることもできます。http://www.csharphelp.com/archives2/archive334.htmlを見て、達成できることのアイデアを得てください

Win32_Process名前空間のMSDNリファレンスも参考になります。

CodeProjectの例も参照してくださいC#を経由して(ほぼ)すべてでWMI:どのようにするに


5

CMSは適切ですが、Visual Studioでサーバーエクスプローラーを使用し、パフォーマンスカウンタータブをいじると、多くの有用なメトリックを取得する方法を理解できます。


3

これは私にとってはうまくいくようです、プロセッサが特定の割合に達するまで待つ例

var cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
int usage = (int) cpuCounter.NextValue();
while (usage == 0 || usage > 80)
{
     Thread.Sleep(250);
     usage = (int)cpuCounter.NextValue();
}

使用量が0のときになぜ眠っているのですか?
watashiSHUN

2

このクラスは1秒ごとに自動的にカウンターをポーリングし、スレッドセーフでもあります。

public class ProcessorUsage
{
    const float sampleFrequencyMillis = 1000;

    protected object syncLock = new object();
    protected PerformanceCounter counter;
    protected float lastSample;
    protected DateTime lastSampleTime;

    /// <summary>
    /// 
    /// </summary>
    public ProcessorUsage()
    {
        this.counter = new PerformanceCounter("Processor", "% Processor Time", "_Total", true);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public float GetCurrentValue()
    {
        if ((DateTime.UtcNow - lastSampleTime).TotalMilliseconds > sampleFrequencyMillis)
        {
            lock (syncLock)
            {
                if ((DateTime.UtcNow - lastSampleTime).TotalMilliseconds > sampleFrequencyMillis)
                {
                    lastSample = counter.NextValue();
                    lastSampleTime = DateTime.UtcNow;
                }
            }
        }

        return lastSample;
    }
}

System.DateTime実際には8バイトの値タイプです。つまり、DateTime変数への割り当てはアトミックではありません。このコードは、32ビットプラットフォームではスレッドセーフではありません。
andrewjs 2016

1

すべてのPerformanceCounterソリューションに1秒のストールを追加する必要がありませんでした。代わりに、WMIソリューションを使用することにしました。1秒の待機/ストールが存在する理由は、を使用するときに読み取り値を正確にするためPerformanceCounterです。ただし、このメソッドを頻繁に呼び出してこの情報を更新する場合は、それを取得するために非同期プロセスを実行することを考えていても、その遅延を常に発生させないようにしてください。

私はここからスニペットを開始し、C#を使用してWMIでCPU使用率を返すと、以下のブログ投稿にソリューションの完全な説明を追加しました。

WMIを使用してC#のすべてのコアのCPU使用率を取得する


ブログにリンクするのではなく、ここに回答を含めてください。
ハーマン

@ヘルマン-私は自分のブログにリンクしていませんでした。私は最初に説明をし、ここの投稿を超えて詳細な回答へのリンクを提供し続けました。
atconway

ブログ投稿のソリューションは、12行のコードのようなものです。他の人にあなたのブログにアクセスしてもらうのではなく、それを回答に含めてみませんか?
ハーマン

@ヘルマン-リンクには詳細な説明が含まれているため、リンクをクリックする際の問題は何ですか。それが「なぜ」部分の詳細なアイデアですか?また、これは7歳です。この正確な投稿と私が当時SOの新人であったことを覚えておくのは難しい。
atconway

リンクが壊れる可能性があり、コアコンテンツがインラインの場合、回答をスキャンする方がはるかに簡単です。私の他の返事がきついので申し訳ありません、私はあなたに苦労を与えるためにここにいません。:)
ハーマン

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.