0

我想实现一个监控当前正在运行的进程的系统。系统获取有关高负载(CPU、内存等)的信息。我调查了两个命名空间。它是 System.Diagnostics 和 System.Management。首先,我编写了一个类来显示所有正在运行的进程的名称、ID 和 CPU 负载。

class Program
{
    static void Main()
    {
        Console.WriteLine("--------------using System.Diagnostics---------------------");
        SysDi();

        Console.WriteLine("----using System.Diagnostics CPU load always zero----------");

        //Here CPU load always zero
        SysDiCpuZero();

        Console.WriteLine("--------------using System.Management---------------------");
        Vmi();

    }


    static void Vmi()
    {
        try
        {
            var searcher = new ManagementObjectSearcher("root\\CIMV2",
                "SELECT * FROM Win32_PerfFormattedData_PerfProc_Process");

            foreach (var queryObj in searcher.Get())
            {
                Console.WriteLine($"Process: {queryObj["Name"]} " +
                                  $"ID: {queryObj["CreatingProcessID"]} " +
                                  $"CPU load: {queryObj["PercentProcessorTime"]}");
            }
        }
        catch (ManagementException e)
        {
            Console.WriteLine("An error occurred while querying for WMI data: " + e.Message);
        }
    }

    static void SysDi()
    {
        var processlist = Process.GetProcesses();
        var counters = new List<PerformanceCounter>();
        foreach (var theprocess in processlist)
        {
            var counter = new PerformanceCounter("Process", "% Processor Time", theprocess.ProcessName);

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

        var i = 0;


        Thread.Sleep(10);
        foreach (var counter in counters)
        {
            Console.WriteLine($"Process: {processlist[i].ProcessName} " +
                              $"ID: {processlist[i].Id} " +
                              $"CPU load: {Math.Round(counter.NextValue(), 5)}");
            ++i;
        }
    }

    static void SysDiCpuZero()
    {
        var processlist = Process.GetProcesses();

        foreach (var theprocess in processlist)
        {
            var counter = new PerformanceCounter("Process", "% Processor Time", theprocess.ProcessName);
            counter.NextValue();

            Console.WriteLine($"Process: {theprocess.ProcessName} " +
              $"ID: {theprocess.Id} " +
              $"CPU load: {Math.Round(counter.NextValue(), 5)}");
        }
    }
}

另外,我注意到在不同的命名空间中,相同的属性具有不同的值。此外,System.Diagnostic 比 System.Management 更快,但带有 CPU 加载数据的方法 SysDi() 看起来不清楚。

在我的情况下使用什么更好?我应该遵循什么标准来选择?

4

2 回答 2

1

StopWatch使用您的代码并在其周围包装's 是结果(毫秒):

WithWMI: 4ms 
WithoutWMI: 2ms

这仅来自一次调用,因此使用Process.GetProcess()速度更快,但也更易于阅读(在我看来),您不必担心魔术字符串(例如查询)。

运行几次后,似乎使用Process.GetProcess()速度更快,在某些运行中它们都花费相同的时间,但通常Process.GetProcess()更快购买几毫秒。

此外,如果您不必使用 WMI,那就不要使用,WMI 会比较慢。

此外,ManagementObjectSearcher与调用相比,查询它似乎可以使用更多的 CPU Process.GetProcess(),我注意到这一点通过调用它们 10000 次并且 WMIProvierHost 整个过程中使用了 50% 的 CPU(我知道这不是调用 WMI 的正常用例对象 1000 次)。

但是这两个调用之间的时间差实际上几乎没有,这一切都归结为可读性,我总是会使用Process.GetProcess过度查询 WMI 来获取进程。

于 2016-06-23T13:01:57.750 回答
0

使用任何更简单、更清洁的东西。将来您可能想要扩展功能并且您的项目可能会增长。初始步骤的简单性将在以后得到回报。WMI 旨在尽一切可能,但开销更大。不过对于大多数情况Diagnostics来说已经足够好了。

时间考虑可以发挥作用,但我不认为你想不断地探测进程,所以这应该不是很重要。尽管如此,这方面也指向Diagnostics

更新

要获得 CPU 负载,您可以使用命名空间中的PerformanceCounterDiagnostics

于 2016-06-23T13:42:46.807 回答