Как получить использование процессора в 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возвращаетfloat . Так зачем присваивать это dynamic? Тогда зачем возвращать это dynamicкак object? Тогда зачем пытаться присвоить objecta 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);
    }
}

Кажется, он правильно измеряет процент использования ЦП 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 было лучше. например this.string computername = Environment.GetEnvironmentVariable ("имя_компьютера");
Дейв

9

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

Также полезным может быть ссылка на MSDN для пространства имен Win32_Process .

См. Также пример CodeProject. Как: (почти) все в WMI через C # .


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

Мне не нравилось добавлять в 1-й стойле все PerformanceCounterрешения. Вместо этого я решил использовать WMIрешение. Причина, по которой существует 1 секунда ожидания / остановки, заключается в том, чтобы показания были точными при использованииPerformanceCounter . Тем не менее, если вы будете часто вызывать этот метод и обновлять эту информацию, я бы посоветовал не постоянно подвергаться этой задержке ... даже если подумал о выполнении асинхронного процесса для его получения.

Я начал с фрагмента здесь. Возвращение загрузки процессора в WMI с использованием C # и добавил полное объяснение решения в своем блоге ниже:

Получить использование ЦП во всех ядрах в C # с помощью WMI


Пожалуйста, включите ответ здесь вместо ссылки на ваш блог.
Герман

@ Герман - я не просто ссылку на свой блог; Я дал объяснение 1-го, и продолжил предоставлять ссылку для подробного ответа помимо поста здесь.
atconway

решение в вашем блоге похоже на 12 строк кода. Почему бы не включить это в свой ответ, кроме попыток заставить людей посетить ваш блог?
Герман

@ Герман - что за проблема с нажатием на ссылку, поскольку она содержит подробное объяснение; это идея «почему» разработка части? Также это 7 лет, просто говорю. Трудно вспомнить этот точный пост, и я тогда был новичком на SO.
atconway

ссылка может быть разорвана, и гораздо проще сканировать ответы, когда основное содержимое встроено. Извините за грубость в моем другом ответе, я здесь не для того, чтобы доставлять вам неприятности. :)
Герман

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.