Bagaimana cara mendapatkan Penggunaan CPU dalam C #?

204

Saya ingin mendapatkan keseluruhan penggunaan CPU total untuk aplikasi dalam C #. Saya telah menemukan banyak cara untuk menggali sifat-sifat proses, tetapi saya hanya ingin penggunaan CPU dari proses, dan total CPU seperti yang Anda dapatkan di TaskManager.

Bagaimana aku melakukan itu?

Peter Mortensen
sumber
36
Bagaimana ini di luar topik? Konyol.
Peter Moore

Jawaban:

205

Anda dapat menggunakan kelas PerformanceCounter dari System.Diagnostics .

Inisialisasi seperti ini:

PerformanceCounter cpuCounter;
PerformanceCounter ramCounter;

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

Konsumsi seperti ini:

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

public string getAvailableRAM(){
            return ramCounter.NextValue()+"MB";
} 
CMS
sumber
80
Nice - tetapi sumber aslinya tampaknya dari sini: zamov.online.fr/EXHTML/CSharp/CSharp_927308.html
Matt Refghi
19
Dari apa yang saya temukan saya harus menggunakan cpuCounter.NextValue () dua kali dan di antara mereka saya harus Sleep (500)
Angel.King.47
Matt benar. Bahkan termasuk bug, seperti lupa kata kunci "kembali".
Mark At Ramp51
8
ya, sepertinya salinan dari tautan itu, jadi tautan untuk referensi yang asli akan menjadi gaya yang bagus. Di sisi lain, itu juga bagus dari CMS untuk memberikan jawaban di sini sehingga pengembang malas tidak harus mencari di seluruh Google untuk menemukan jawaban yang sama. : o)
BerggreenDK
13
Anda harus memanggil .NextValue dua kali, dengan System.Threading.Thread.Sleep panggilan di antara (1000ms sudah cukup). Lihat blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx untuk informasi lebih lanjut tentang mengapa ini diperlukan, tetapi ringkasan tingkat tinggi adalah bahwa Anda perlu dua sampel untuk menghitung nilai, dan Anda perlu memberi OS waktu untuk mendapatkan keduanya.
Cleggy
63

Sedikit lebih banyak dari yang dibutuhkan kembali tetapi saya menggunakan kode timer tambahan untuk melacak dan mengingatkan jika penggunaan CPU 90% atau lebih tinggi untuk periode 1 menit atau lebih lama.

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";
    }
}
Khalid Rahaman
sumber
7
Di mana getRAMCounter ()?
Dieter B
1
cpuCounter.NextValuemengembalikan afloat . Jadi mengapa menugaskannya ke dynamic? Lalu mengapa mengembalikannya dynamicsebagai object? Lalu mengapa mencoba untuk menetapkan objectke intdalam baris int cpuPercent = getCPUCounter()? (Kode itu tidak akan dikompilasi.)
Wyck
21

Setelah menghabiskan waktu membaca beberapa utas berbeda yang sepertinya cukup rumit, saya membuat ini. Saya membutuhkannya untuk mesin 8 inti di mana saya ingin memonitor SQL server. Untuk kode di bawah ini maka saya meneruskan "sqlservr" sebagai 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);
    }
}

Tampaknya mengukur dengan benar% dari CPU yang digunakan oleh SQL pada server 8 core saya.

MtnManChris
sumber
total_cpu harus PerformanceCounter ("Processor"), bukan PerformanceCounter ("Process") .. jika tidak, Anda hanya mendapatkan 100% * jumlah core.
masak steve
3
Di mana Anda menetapkan donetrue? Kecuali saya telah melewatkan sesuatu, ini tampaknya menjadi loop tanpa akhir:while(!done){...}
Manfred
@Manfred Ini memang loop tanpa akhir
Jenny
16

Tidak apa-apa, saya mengerti! Terima kasih atas bantuan Anda!

Berikut adalah kode untuk melakukannya:

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;
}
xoxo
sumber
Menambahkan nama server bukannya variabel yang dipilih Server lebih baik. seperti this.string computername = Environment.GetEnvironmentVariable ("computername");
Dave
5

CMS benar, tetapi juga jika Anda menggunakan server explorer di studio visual dan bermain-main dengan tab penghitung kinerja, maka Anda dapat mengetahui cara mendapatkan banyak metrik yang bermanfaat.

Tarks
sumber
3

Ini sepertinya bekerja untuk saya, contoh menunggu sampai prosesor mencapai persentase tertentu

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();
}
Jay Byford-Rew
sumber
mengapa kamu tidur ketika penggunaannya adalah 0?
watashiSHUN
2

Kelas ini secara otomatis polling penghitung setiap 1 detik dan juga aman thread:

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;
    }
}
Colin Breame
sumber
System.DateTimesebenarnya merupakan tipe nilai 8 byte yang berarti bahwa penugasan ke suatu DateTimevariabel bukan atom. Kode ini tidak aman untuk platform 32 bit.
andrewjs
1

Saya tidak suka harus menambahkan di kios 1 detik untuk semua PerformanceCountersolusi. Sebaliknya saya memilih untuk menggunakan WMIsolusi. Alasan 1 detik menunggu / kios ada adalah untuk memungkinkan pembacaan menjadi akurat saat menggunakan a PerformanceCounter. Namun jika Anda sering memanggil metode ini dan menyegarkan informasi ini, saya sarankan untuk tidak terus-menerus harus menunda itu ... bahkan jika berpikir untuk melakukan proses async untuk mendapatkannya.

Saya mulai dengan cuplikan dari sini Mengembalikan penggunaan CPU di WMI menggunakan C # dan menambahkan penjelasan lengkap tentang solusi pada posting blog saya di bawah ini:

Dapatkan Penggunaan CPU Di Seluruh Core Di C # Menggunakan WMI

atconway
sumber
Harap sertakan jawabannya di sini daripada menautkan ke blog Anda.
Herman
@ Jerman - Saya tidak hanya menautkan ke blog saya; Saya memberikan penjelasan ke-1, dan terus memberikan tautan untuk jawaban mendalam di luar pos di sini.
atconway
solusi dalam posting blog Anda seperti 12 baris kode. Mengapa tidak memasukkan itu dalam jawaban Anda selain mencoba membuat orang mengunjungi blog Anda?
Herman
@ Jerman - Apa masalahnya dengan mengklik tautan karena berisi penjelasan yang mendalam; Itulah gagasan elaborasi porsi 'mengapa'? Ini juga 7 tahun, hanya mengatakan. Sulit untuk mengingat posting yang tepat ini dan saya menjadi pemula di SO saat itu.
atconway
tautan bisa rusak, dan jauh lebih mudah untuk memindai jawaban ketika konten intinya sejajar. Maaf karena keras dalam balasan saya yang lain, saya di sini bukan untuk memberi Anda waktu yang sulit. :)
Herman
0
public int GetCpuUsage()
{
var cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total", Environment.MachineName);
cpuCounter.NextValue();
System.Threading.Thread.Sleep(1000); //This avoid that answer always 0
return (int)cpuCounter.NextValue();
}

Informasi asli di tautan ini https://gavindraper.com/2011/03/01/retrieving-accurate-cpu-usage-in-c/

araad1992
sumber