วิธีรับการใช้งาน CPU ใน C #


204

ฉันต้องการรับการใช้งาน CPU ทั้งหมดโดยรวมสำหรับแอปพลิเคชันใน C # ฉันพบหลายวิธีที่จะขุดลงในคุณสมบัติของกระบวนการ แต่ฉันต้องการเพียงการใช้งาน CPU ของกระบวนการและ CPU ทั้งหมดเช่นเดียวกับที่คุณได้รับใน TaskManager

ฉันจะทำอย่างไร



36
หัวข้อนี้เป็นอย่างไรในโลก ไร้สาระ.
Peter Moore

คำตอบ:


205

คุณสามารถใช้PerformanceCounterระดับจากSystem.Diagnostics

เริ่มต้นเช่นนี้:

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 () สองครั้งและระหว่างพวกเขาฉันต้องนอน (500)
Angel.King.47

แมตต์ถูกต้อง แม้กระทั่งรวมถึงข้อบกพร่องเช่นลืมคำหลัก "คืน"
Mark At Ramp51

8
ใช่ดูเหมือนว่าสำเนาจากลิงก์นั้นดังนั้นลิงก์สำหรับการอ้างอิงของต้นฉบับจะเป็นสไตล์ที่ดี ในทางกลับกันมันก็ดีของ CMS ที่จะให้คำตอบที่นี่ดังนั้นนักพัฒนาที่ขี้เกียจไม่ต้องค้นหาทั่ว Google เพื่อค้นหาคำตอบเดียวกัน : o)
BerggreenDK

13
คุณจะต้องโทรหา. NextValue สองครั้งโดยใช้ System.Threading.Thread.Sleep call ในระหว่าง (1000ms ควรพอเพียง) ดูblogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspxสำหรับข้อมูลเพิ่มเติมเกี่ยวกับสาเหตุที่ต้องดำเนินการ แต่สรุประดับสูงคือคุณต้องมีตัวอย่างสองตัวอย่างเพื่อคำนวณค่า และคุณต้องให้เวลากับระบบปฏิบัติการในการรับทั้งสองอย่างนี้
Cleggy

63

น้อยกว่าถูก requsted แต่ฉันใช้รหัสตัวจับเวลาพิเศษเพื่อติดตามและแจ้งเตือนหากการใช้งาน CPU 90% หรือสูงกว่าในช่วงเวลา 1 นาทีหรือนานกว่านั้น

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 อยู่ที่ไหน ()
Dieter B

1
cpuCounter.NextValuefloatผลตอบแทน เหตุใดจึงต้องกำหนดให้dynamic? แล้วทำไมกลับมาว่าdynamicเป็นobject? ถ้าอย่างนั้นลองกำหนดให้objectกับ a intในบรรทัดint cpuPercent = getCPUCounter()ทำไม? (รหัสนั้นจะไม่คอมไพล์)
Wyck

21

หลังจากใช้เวลาอ่านหัวข้อที่แตกต่างกันสองสามข้อซึ่งดูค่อนข้างซับซ้อนฉันก็คิดเรื่องนี้ ฉันต้องการมันสำหรับเครื่อง 8 คอร์ที่ฉันต้องการตรวจสอบเซิร์ฟเวอร์ SQL สำหรับรหัสด้านล่างแล้วฉันผ่าน "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);
    }
}

ดูเหมือนว่าจะวัด% ของ CPU ที่ SQL ใช้อย่างถูกต้องบนเซิร์ฟเวอร์หลัก 8 ตัวของฉัน


total_cpu ควรเป็น PerformanceCounter ("Processor") ไม่ใช่ PerformanceCounter ("Process") .. มิฉะนั้นคุณจะได้รับ 100% * จำนวนคอร์
สตีฟทำอาหาร

3
คุณตั้งค่าdoneเป็นจริงที่ไหน ถ้าฉันไม่ได้มองข้ามสิ่งนี้ดูเหมือนว่าจะวนซ้ำไม่รู้จบ:while(!done){...}
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;
}

เพิ่มการรับชื่อเซิร์ฟเวอร์แทนตัวแปรที่เลือกเซิร์ฟเวอร์ที่ดีกว่า like this.string computername = Environment.GetEnvironmentVariable ("computername");
เดฟ

9

คุณสามารถใช้ WMI เพื่อรับข้อมูลเปอร์เซ็นต์ CPU คุณสามารถเข้าสู่ระบบคอมพิวเตอร์ระยะไกลหากคุณมีสิทธิ์ที่ถูกต้อง ดูhttp://www.csharphelp.com/archives2/archive334.htmlเพื่อรับทราบว่าคุณสามารถทำอะไรได้บ้าง

นอกจากนี้ยังมีประโยชน์อาจอ้างอิง MSDN สำหรับnamespace Win32_Process

ดูยังมี CodeProject ตัวอย่างวิธีการ: (เกือบ) ทุกอย่างใน WMI ผ่าน C #


5

CMS นั้นถูกต้อง แต่ถ้าคุณใช้เซิร์ฟเวอร์ explorer ใน 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

1

ฉันไม่ต้องการเพิ่มในแผงลอย 1 วินาทีเพื่อPerformanceCounterแก้ปัญหาทั้งหมด ฉันเลือกใช้WMIวิธีแก้ปัญหาแทน เหตุผลที่ 1 รอสอง / PerformanceCounterแผงลอยที่มีอยู่คือการช่วยให้การอ่านที่ถูกต้องเมื่อใช้ อย่างไรก็ตามหากคุณโทรหาวิธีนี้บ่อยครั้งและรีเฟรชข้อมูลนี้ฉันไม่แนะนำให้ทำอย่างต่อเนื่องเพื่อให้เกิดความล่าช้านั้น ... แม้ว่าจะคิดว่าจะทำกระบวนการ async เพื่อรับข้อมูลก็ตาม

ฉันเริ่มด้วยตัวอย่างจากที่นี่กลับมาใช้งาน CPU ใน WMI โดยใช้ C #และเพิ่มคำอธิบายแบบเต็มของการแก้ปัญหาในโพสต์บล็อกของฉันด้านล่าง:

รับการใช้งาน CPU ทั่วทั้งคอร์โดยใช้ WMI


โปรดใส่คำตอบที่นี่แทนที่จะเชื่อมโยงไปยังบล็อกของคุณ
เฮอร์แมน

@ เฮอร์แมน - ฉันไม่ได้แค่ลิงค์ไปยังบล็อกของฉัน ฉันให้คำอธิบายที่ 1 และดำเนินการเพื่อให้ลิงก์สำหรับคำตอบเชิงลึกนอกเหนือจากโพสต์ที่นี่
atconway

วิธีแก้ปัญหาในโพสต์บล็อกของคุณนั้นเหมือนกับรหัส 12 บรรทัด ทำไมไม่รวมไว้ในคำตอบของคุณนอกเหนือจากการพยายามให้คนอื่นมาเยี่ยมชมบล็อกของคุณ
เฮอร์แมน

@Herman - ปัญหาในการคลิกที่ลิงค์เนื่องจากมีคำอธิบายในเชิงลึก นั่นเป็นความคิดที่ว่า นอกจากนี้ยังมีอายุ 7 ปีเพียงแค่พูดว่า ยากที่จะจำโพสต์ที่แน่นอนนี้และฉันเป็น newb บนดังนั้นกลับมาแล้ว
atconway

ลิงก์อาจเสียหายและง่ายต่อการสแกนคำตอบเมื่อเนื้อหาหลักเป็นแบบอินไลน์ ขออภัยที่มีความเมตตาในคำตอบอื่น ๆ ของฉันฉันไม่ได้อยู่ที่นี่เพื่อให้คุณได้รับความยากลำบาก :)
เฮอร์แมน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.