C #에서 CPU 사용량을 얻는 방법?


답변:


205

System.Diagnostics 에서 PerformanceCounter 클래스를 사용할 수 있습니다 .

다음과 같이 초기화하십시오.

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 ()를 두 번 사용해야하고 그들 사이에서 잠을
자야했습니다

매트가 맞아. "return"키워드를 잊어 버리는 것과 같은 버그도 포함합니다.
Mark At Ramp51

8
예, 그것은 그 링크의 사본처럼 보이므로 원본을 참조하기위한 링크는 멋진 스타일 일 것입니다. 반면에 CMS는 여기에 답변을 제공하기 때문에 게으른 개발자가 동일한 답변을 찾기 위해 Google 전체를 검색 할 필요가 없습니다. : o)
BerggreenDK

13
System.Threading.Thread.Sleep 호출을 사용하여 .NextValue를 두 번 호출해야합니다 (1000ms이면 충분 함). 이것이 왜 필요한지에 대한 자세한 내용 은 blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx 를 참조하십시오 . 그러나 높은 수준의 요약은 값을 계산하기 위해 두 개의 샘플이 필요하다는 것입니다. 두 가지를 모두 얻을 수있는 시간을 OS에 제공해야합니다.
Cleggy

63

필요한 것보다 조금 더 많았지 만 여분의 타이머 코드를 사용하여 1 분 이상의 지속 시간 동안 CPU 사용량이 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 ()는 어디에 있습니까?
Dieter B

1
cpuCounter.NextValue를 반환합니다float . 그렇다면 왜 그것을 dynamic? 그럼 왜 그 반환 dynamic하여 AS를 object? 그럼 왜를 할당하려고 objectint라인에 int cpuPercent = getCPUCounter()? (그 코드는 컴파일되지 않습니다.)
Wyck

21

꽤 복잡해 보였던 몇 가지 다른 스레드를 읽는 데 시간을 보낸 후 이것을 생각해 냈습니다. SQL Server를 모니터링하려는 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 ( "Process")가 아닌 PerformanceCounter ( "Processor") 여야합니다. 그렇지 않으면 100 % * 코어 수만 얻습니다.
Steve 요리 2

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 대신 서버 이름을 얻는 것이 좋습니다. 다음과 같이. 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

1

나는 모든 PerformanceCounter솔루션에 1 초 스톨을 추가하는 것을 좋아하지 않았습니다 . 대신 WMI솔루션 을 사용하기로 결정했습니다 . 1 초 대기 / 스톨이 존재하는 이유는PerformanceCounter 입니다. 그러나이 방법을 자주 호출 하고이 정보를 새로 고치면 비동기 프로세스를 수행하려고 생각하더라도 계속 지연이 발생하지 않아야합니다.

여기에서 미리보기 시작 C #을 사용 WMI에서 CPU 사용을 반환 하고 아래에있는 내 블로그 게시물에 솔루션에 대한 자세한 설명을 추가 :

WMI를 사용하여 C #의 모든 코어에서 CPU 사용량 가져 오기


블로그에 연결하는 대신 여기에 답변을 포함하십시오.
허먼

@Herman-블로그에 링크하지 않았습니다. 나는 첫 번째로 설명을하고 여기 게시물을 넘어 심층 답변에 대한 링크를 제공했습니다.
atconway

블로그 게시물의 솔루션은 12 줄의 코드와 같습니다. 사람들이 귀하의 블로그를 방문하도록하는 것 이외의 답변에 포함시키지 않겠습니까?
허먼

@Herman-자세한 설명이 포함 된 링크를 클릭하면 문제가 발생합니다. 그것이 '왜'부분 정교화라는 생각입니까? 또한 이것은 7 살입니다. 이 정확한 게시물을 기억하기가 어려웠고 그때 나는 그렇게 새롭습니다.
atconway

링크가 끊어 질 수 있으며 핵심 컨텐츠가 인라인 일 때 답변을 스캔하는 것이 훨씬 쉽습니다. 다른 답장으로 가혹하게해서 죄송합니다. 힘든 시간을 보내려고 오지 않았습니다. :)
허먼

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.