Як отримати використання процесора в C #?


204

Я хочу отримати загальне загальне використання процесора для програми в C #. Я знайшов багато способів розібратися у властивостях процесів, але хочу лише використання процесорів процесорів та загального процесора, як ви отримуєте в TaskManager.

Як це зробити?



36
Як на землі це поза темою? Смішно.
Пітер Мур

Відповіді:


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
Метт Рефгі

19
З того, що я виявив, мені довелося два рази використовувати cpuCounter.NextValue (), і між ними мені довелося спати (500)
Angel.King.47

Метт правий. Навіть включаючи помилки, як-от забути ключове слово "return".
Позначити в Ramp51

8
так, це схоже на копію з цього посилання, тому посилання на посилання на оригінал було б гарним стилем. З іншого боку, також приємно CMS надати тут відповідь, тому ледачим розробникам не доведеться шукати в усьому Google, щоб знайти ту саму відповідь. : o)
BerggreenDK

13
Вам потрібно буде зателефонувати .NextValue двічі, з системою System.Threading.Thread.Sleep-дзвінок між ними (1000мс повинно вистачити). Див. Blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx для отримання додаткової інформації про те, чому це потрібно, але резюме високого рівня полягає в тому, що для обчислення значення потрібно два зразки, і вам потрібно дати часу ОС, щоб отримати і те і інше.
Cleggy

63

Трохи більше, ніж було відновлено, але я використовую додатковий код таймера для відстеження та оповіщення, якщо використання процесора становить 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 ()?
Дітер Б

1
cpuCounter.NextValueповертає afloat . То навіщо призначати його до dynamic? Тоді чому повернутися , що dynamicяк object? Тоді навіщо намагатися призначити objectзнак intу рядку int cpuPercent = getCPUCounter()? (Цей код не збирається.)
Вік

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 ("Процесор"), а не PerformanceCounter ("Процес") .. інакше ви просто отримаєте 100% * кількість ядер.
кухар Стів

3
Де ви встановите doneправду? Якщо я щось не помітив, це здається нескінченним циклом:while(!done){...}
Манфред

@Manfred Це дійсно нескінченна петля
Дженні

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 було краще. like this.string computername = Environment.GetEnvironmentVariable ("ім'я комп'ютера");
Дейв

9

Ви можете використовувати WMI для отримання інформації про відсоток процесора. Ви навіть можете увійти у віддалений комп'ютер, якщо у вас є правильні дозволи. Подивіться на http://www.csharphelp.com/archives2/archive334.html щоб отримати уявлення про те, що ви можете досягти.

Також корисною може бути посилання MSDN для Win32_Process простору імен .

Дивіться також приклад CodeProject Як: (майже) все у WMI через C # .


5

CMS має на це право, але також якщо ви використовуєте провідник сервера у візуальній студії та граєте за допомогою вкладки лічильника продуктивності, то ви можете зрозуміти, як отримати багато корисних показників.


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 . Однак якщо ви часто закликаєте цей метод і оновлюєте цю інформацію, я б радив не постійно зазнавати цієї затримки ... навіть якщо думати про процес асинхронізації, щоб отримати її.

Я почав з фрагмента звідси. Повернення використання процесора у WMI за допомогою C # та додав повне пояснення рішення у своєму дописі в блозі нижче:

Отримайте використання процесора у всіх ядрах C # за допомогою WMI


Будь ласка, включіть відповідь тут, а не посилаючись на свій блог.
Герман

@Herman - я не просто посилався на свій блог; Я дав пояснення 1-го і продовжив надавати посилання для глибокої відповіді поза повідомленням тут.
atconway

рішення у вашій публікації блогу - це як 12 рядків коду. Чому б не включити це у свою відповідь, крім того, щоб намагатися примусити людей відвідувати ваш блог?
Герман

@Herman - у чому полягає проблема з натисканням на посилання, оскільки воно містить поглиблене пояснення; ось ідея розробки частини "чому"? Також це 7 років, просто кажу. Важко запам’ятати цю точну посаду, і тоді я був новачком на SO.
atconway

посилання може розірватися, і набагато простіше сканувати відповіді, коли основний вміст є вбудованим. Вибачте за те, що в моїй іншій відповіді ви були суворими, я не тут, щоб дати вам важкий час. :)
Герман

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.