在 C# 中异步检索 Cpu 用法

Retrieve Cpu usage asynchronously in C#

我想使用 c# 检索我的系统的 cpu 使用情况。我读到我必须调用方法 NextValue() 然后等待大约一秒钟并再次调用 NextValue() 方法。 我想异步执行以不延迟我的 UI 线程,所以我编写了以下代码

    public Task<float> GetCpuPerformanceAsync()
    {
        return Task.Run(() =>
        {
            CpuPerformance.NextValue();
            Task.Delay(1000);
            return CpuPerformance.NextValue();
        });
    }

这是CpuPerformance

的声明
CpuPerformance = new PerformanceCounter("Processor Information", "% Processor Time", "_Total");

第一次调用上面显示的异步方法时 returns 我实际使用 cpu 但是几秒后再次调用它只显示 0 或 100 这不一致使用我的任务管理器中显示的用法

有人可以帮我解决这个问题吗?

不幸的是,dotnetfiddle 不允许我使用 PerformanceCounters,但这应该可以正常工作:

public class Helper // Of course, you do not necessarily need an extra class ...
{
    // Lazy Pattern: Will create an instance on first usage.
    private static Lazy<PerformanceCounter> CpuPerformance = new Lazy<PerformanceCounter>(() => {
        // this will be used as factory to create the instance ...
        // 1. create counter
        PerformanceCounter pc = new PerformanceCounter("Processor Information", "% Processor Time", "_Total");
        // "warm up"
        pc.NextValue();
        Thread.Sleep(1000);
        // return ready-to-use instance
        return pc;
        // ^^ this will be executed only _once_.
    });

    // Read-Only Property uses Lazy to ensure instance exists, then use it.
    public static float CpuTimeInPercent {
        get { return CpuPerformance.Value.NextValue(); }
    }
}

用法:

Console.WriteLine("Performance: {0}%", Helper.CpuTimeInPercent);

这是使用他们提出的技术替代@Fildor 的答案,但它避免了在第一次访问 CpuTimeInPercent 时让线程休眠。

public static class Helper
{
    private static readonly Task<PerformanceCounter> performanceCounter = GetCounter();

    private static async Task<PerformanceCounter> GetCounter()
    {
        PerformanceCounter pc = new PerformanceCounter("Processor Information", "% Processor Time", "_Total");
        // "warm up"
        pc.NextValue();
        await Task.Delay(1000);
        // return ready-to-use instance
        return pc;
    }

    public static async Task<float> GetCpuTimeInPercentAsync()
    {
        var counter = await performanceCounter;
        return counter.NextValue();
    }
}

这将在第一次执行 performanceCounter 之前的某个时刻开始执行 GetCounter()(可能是在加载程序集时,也可能是在调用 GetCounter() 时) ,运行时在这里有很大的自由度)。如果您在它进行预热时调用 GetCpuTimeInPercentAsync,那么它会等到它完成后再获取 CPU 用法。如果您随后调用它,或者在它完成预热后调用它,那么它将 return 立即使用 CPU。