Неправильно рассчитано использование процессора с использованием C # и WMI - PullRequest
3 голосов
/ 16 декабря 2010

Это моя функция для перечисления процессов в окне Windows и расчета процента использования ЦП для каждого процесса, но результаты неверны.

Использование ЦП не составляет до 100%, но больше похоже на 120%или 130% и я не знаю, что я делаю не так.Похоже, что он рассчитывает правильную загрузку ЦП для таких приложений varoius, как firefox, VS2010, office, ..., но имеет проблемы с System Idle Process.

public List<ProcInfo> GetRunningProcesses()
{
    List<ProcInfo> allProcesses = new List<ProcInfo>();
    UInt64 currentProcessCpuTime = 0;
    UInt64 allProcessCpuTime = 0;

    SelectQuery wmiQuery = new SelectQuery("SELECT Name, Description, ProcessId, KernelModeTime, UserModeTime FROM Win32_Process");
    ManagementObjectSearcher oSearcher = new ManagementObjectSearcher(connectionScope, wmiQuery);
    ManagementObjectCollection moc = oSearcher.Get();

    foreach (ManagementObject mo in moc)
    {
        allProcessCpuTime += (UInt64)mo["KernelModeTime"] + (UInt64)mo["UserModeTime"];
    }

    foreach (ManagementObject mo in moc)
    {
        currentProcessCpuTime = (UInt64)mo["KernelModeTime"] + (UInt64)mo["UserModeTime"];
        allProcesses.Add(new ProcInfo((string)mo["Name"], (string)mo["Description"], (UInt32)mo["ProcessId"], (currentProcessCpuTime / (double)allProcessCpuTime * 100));
    }

    return allProcesses;
}

РЕДАКТИРОВАТЬ:

Я обнаружил, что моя функция все неправильно.

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

Ответы [ 3 ]

3 голосов
/ 26 декабря 2010

Вот код C # со счетчиками производительности:

public static void DumpProcessesCpu(string machineName)
{
    List<PerformanceCounter> counters = new List<PerformanceCounter>();

    foreach (Process process in Process.GetProcesses(machineName))
    {
        PerformanceCounter processorTimeCounter = new PerformanceCounter(
            "Process",
            "% Processor Time",
            process.ProcessName,
            machineName);

        processorTimeCounter.NextValue();
        counters.Add(processorTimeCounter);
    }

    Thread.Sleep(1000); // 1 second wait, needed to get a sample

    foreach (PerformanceCounter processorTimeCounter in counters)
    {
        Console.WriteLine("Process:{0} CPU% {1}",
            processorTimeCounter.InstanceName,
            processorTimeCounter.NextValue());
    }
}

Это вдохновляет отсюда: http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx Вы не можете быть быстрее, чем это, причина, почему объясняется в статье,По сути, вам нужно прочитать значение дважды, чтобы получить правильное значение, поэтому вам нужно подождать между выборками.

Однако, в зависимости от того, что вы хотите сделать, например, предположим, что вы хотите написать "Диспетчер удаленных задач », вы можете закодировать все это в фоновом задании (потоке) и регулярно обновлять значения, чтобы конечный пользователь не видел задержку между выборками.

1 голос
/ 26 декабря 2010
        var mos = new ManagementObjectSearcher("SELECT * FROM Win32_PerfRawData_PerfProc_Process");
        var run1 = mos.Get().Cast<ManagementObject>().ToDictionary(mo => mo.Properties["Name"].Value, mo => (ulong)mo.Properties["PercentProcessorTime"].Value);
        Thread.Sleep(570); // can be an arbitrary number
        var run2 = mos.Get().Cast<ManagementObject>().ToDictionary(mo => mo.Properties["Name"].Value, mo => (ulong)mo.Properties["PercentProcessorTime"].Value);

        var total = run2["_Total"] - run1["_Total"];

        foreach (var kvp in run1)
        {
            var proc = kvp.Key;
            var p1 = kvp.Value;
            if (run2.ContainsKey(proc))
            {
                var p2 = run2[proc];
                Console.WriteLine("{0}: {1:P}", proc, (double)(p2 - p1) / total);
            }
        }
0 голосов
/ 25 января 2017

Вот блок кода C #, протестированный и проверенный, и благодаря fejesjoco я использовал его код и сделал тест, чтобы заставить его работать.

public class CPUUtilizationTests
{

    [Test]
    public void TestPercentProcessorTime()
    {
        Assert.That(PercentProcessorTime("Idle"), Is.Not.GreaterThan(100.0));
    }

    public float PercentProcessorTime(string processName)
    {
        var mos = new ManagementObjectSearcher("SELECT * FROM Win32_PerfRawData_PerfProc_Process");
        var run1 = mos.Get().Cast<ManagementObject>().ToDictionary(mo => mo.Properties["Name"].Value, mo => mo);
        System.Threading.Thread.Sleep(1000); // can be an arbitrary number
        var run2 = mos.Get().Cast<ManagementObject>().ToDictionary(mo => mo.Properties["Name"].Value, mo => mo);

        if (!run2.ContainsKey(processName)) throw new Exception(string.Format("Process not found: {0}", processName));

        string percentageProcessorTime = "PercentProcessorTime";
        string total = "_Total";

        ulong percentageDiff = (ulong)run2[processName][percentageProcessorTime] - (ulong)run1[processName][percentageProcessorTime];
        ulong totalDiff = (ulong)run2[total][percentageProcessorTime] - (ulong)run1[total][percentageProcessorTime];

        return ((float)percentageDiff / (float)totalDiff)*100.0f;
    }

}
...