C# 系统 CPU 使用情况并与 Windows 任务管理器同步

2024-05-09

这是一个由两部分组成的问题,我想将我的代码发布到堆栈上以帮助其他人完成相同的任务。

问题一:

我有一个代码子集,我相信它可以根据测量间隔正确测量 CPU 使用情况(根据检索的时间跨系统中的尽可能多的核心) - 我在线程调用中使用 1 秒。

我必须从网上极少数的文章和 C++ 代码中破译这一点。我的问题是,对于问题1,我所做的正确吗?

有时返回的值是负数,这就是我乘以-1的原因。再次,由于文档很少,我假设这就是我应该做的。

我有以下代码:

public static class Processor
{
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool GetSystemTimes(out ComTypes.FILETIME lpIdleTime, out ComTypes.FILETIME lpKernelTime, out ComTypes.FILETIME lpUserTime);

    private static TimeSpan _sysIdleOldTs;
    private static TimeSpan _sysKernelOldTs;
    private static TimeSpan _sysUserOldTs;

    static Processor()
    {
    }

    public static void Test()
    {
        ComTypes.FILETIME sysIdle, sysKernel, sysUser;

        if(GetSystemTimes(out sysIdle, out sysKernel, out sysUser))
        {
            TimeSpan sysIdleTs = GetTimeSpanFromFileTime(sysIdle);
            TimeSpan sysKernelTs = GetTimeSpanFromFileTime(sysKernel);
            TimeSpan sysUserTs = GetTimeSpanFromFileTime(sysUser);

            TimeSpan sysIdleDiffenceTs = sysIdleTs.Subtract(_sysIdleOldTs);
            TimeSpan sysKernelDiffenceTs = sysKernelTs.Subtract(_sysKernelOldTs);
            TimeSpan sysUserDiffenceTs = sysUserTs.Subtract(_sysUserOldTs);

            _sysIdleOldTs = sysIdleTs;
            _sysKernelOldTs = sysKernelTs;
            _sysUserOldTs = sysUserTs;

            TimeSpan system = sysKernelDiffenceTs.Add(sysUserDiffenceTs);

            Double cpuUsage = (((system.Subtract(sysIdleDiffenceTs).TotalMilliseconds) * 100) / system.TotalMilliseconds);

            if (cpuUsage < 0)
            {
                Console.WriteLine("CPU: " + ((int) (cpuUsage)*-1) + "%");
            }
            else
            {
                Console.WriteLine("CPU: " + (int) (cpuUsage) + "%");
            }
            Console.WriteLine("");
        }
        else
        {
            Console.WriteLine("Couldn't get CPU usage!");
            Console.WriteLine("");
        }
    }

    private static TimeSpan GetTimeSpanFromFileTime(ComTypes.FILETIME time)
    {
        return TimeSpan.FromMilliseconds((((ulong)time.dwHighDateTime << 32) + (uint)time.dwLowDateTime) * 0.000001);
    }
}

问题2:

无论如何,我是否可以将程序中的线程与 Windows 任务管理器的线程同步,以便将测量数据(例如 CPU 使用率)与上述代码相匹配?

我的意思是,如果您打开 Windows 任务管理器,您会注意到它每秒轮询一次 - 实际上它不需要比这个少。我想做的就是将时间与我的线程相匹配。

因此,当 Windows 任务管理器轮询时,我的线程也会轮询。


一些注意事项:

我不想使用性能计数器或 .NET 内置方法。事实上,我相信 - 根据我所读到的内容,.NET 没有计算计算机上 CPU 使用率的方法,否则需要性能计数器。

性能计数器有开销,此外还会导致 GC 增长,更不用说调用下一个结果的延迟。虽然我的软件不需要实时性能,但我确实需要它具有尽可能高的响应速度并使用尽可能少的 CPU 时间。上面的代码可以在不到一毫秒的时间内调用并返回。事实上,在我的开发机器上,时间跨度差异显示为 0ms。 我不认为性能计数器具有如此灵敏的响应能力。

如果您好奇的话,我的软件正在收集许多项目,CPU、内存、事件日志项目等,其中所有这些都需要在下一次轮询之前(1 秒后)收集并存储在 SQL CE 中。然而,每个任务、项目都在其自己的线程上以促进这一点。

另外,上面的代码无论如何都没有优化,你会注意到我还没有评论它。原因是我想在优化等之前确保它是正确的。

Update 1

根据我一路上发表的评论,我删除了额外的“系统”时间跨度,因为它不是必需的,并修改了检索“CPU 使用率”的行并对其进行了适当的转换。

int cpuUsage = (int)(((sysKernelDifferenceTs.Add(sysUserDifferenceTs).Subtract(sysIdleDifferenceTs).TotalMilliseconds) * 100.00) / sysKernelDifferenceTs.Add(sysUserDifferenceTs).TotalMilliseconds);

虽然我仍然不确定这个公式。虽然它似乎非常准确,但它有时会返回负数,这就是为什么我将其乘以 -1(如果是这种情况)。毕竟,不存在 -2% CPU 使用率等情况。

Update 2

所以我使用“System.Diagnostics.PerformanceCounter”做了一个简单的测试。虽然非常方便并且完全按照预期执行,但它确实会产生开销。

以下是我的观察:

  • 性能计数器的初始化花费了更长的时间。在我的 i7 2.6 Ghz 上大约长了三秒。
  • 性能计数器似乎还仅仅通过使用它就增加了大约 5MB 的 RAM 使用量。我的意思是:使用上面的代码,我的应用程序最大内存为 7.5MB。使用性能计数器时,它“起始”为 12.5MB。
  • 在 5 秒的时间内,我的线程运行了 5 次 - 每秒一次,我的应用程序的内存增长了 1 MB,这种增长与时间一致,尽管在我的情况下它确实稳定了 3-4MB以上开始。因此,如果我的应用程序的内存通常为 7.5MB,上面的代码,则 PC 代码稳定在 16.5MB 内存 - 比上面的代码增加了 9MB。Note:上面的代码does not导致这种增加。

因此,如果您的应用程序是以资源使用和计时为关键的方式构建的,那么由于这些原因,我建议不要使用性能计数器。否则就继续吧,因为它可以正常工作,不会出现任何混乱。

至于我的应用程序,性能计数器将不利于我的软件的目的。


我认为你的公式中有一个错误。您希望基本上计算 CPU 使用率,如下所示:

CPU Usage = KernelTimeDiff + UserTimeDiff
            --------------------------------------------
            KernelTimeDiff + UserTimeDiff + IdleTimeDiff

因此,对代码进行快速修改如下:

        //  TimeSpan system = sysKernelDiffenceTs.Add(sysUserDiffenceTs);
        //Double cpuUsage = (((system.Subtract(sysIdleDiffenceTs).TotalMilliseconds) * 100) / system.TotalMilliseconds); 

        TimeSpan totaltime = sysKernelDiffenceTs.Add(sysUserDiffenceTs);
        totaltime = totaltime.Add(sysIdleDifferenceTs);
        int cpuUsage = 100 - (sysIdleDifferenceTs.TotalMilliseconds * 100) / totaltime.TotalMilliseconds;
       Console.WriteLine("CPU: " + cpuUsage + "%");

您最初将 cpuUsage 声明为“Double”。我不确定您是否想要浮点精度,但在您的代码中,您肯定没有得到除整数精度之外的任何东西,因为赋值语句只是进行整数数学运算。如果您需要更高的计算精度,您可以通过混合一些浮点来轻松获得它:

Double cpuUsage = 100.0 - (sysIdleDifferenceTs.TotalMilliseconds * 100.0) /totaltime.TotalMilliseconds;

另外,关于与任务管理器同步。据我了解,任务管理器使用性能计数器。 (我怀疑 GetSystemTimes 正在幕后进行性能计数器调用,但也许不是)。我也不知道为什么你不使用性能计数器。 “%处理时间”计数器是一个即时样本计数器,不需要计算与先前结果的差异。 (每个逻辑 CPU 有一个)。使用 PDH 帮助程序函数而不是旧的注册表项 API 来获取它。您可以从非托管 C/C++ DLL 中执行此操作,该 DLL 将“GetCpuUsage”函数导出回 C# 代码。但我也不知道为什么你不能直接从 C# 调用 PDH 函数。我不知道你所说的这个开销。我也不确定我是否理解您提到的“调用下一个结果的延迟”。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# 系统 CPU 使用情况并与 Windows 任务管理器同步 的相关文章

随机推荐

  • 如何在 Java 中安装附加包?

    我对 Java 很陌生 我想使用名为的包中的一些功能daj 教程代码有以下几行 import daj import java util import java lang Math import Msg 但第一行和第四行会产生红色下划线 导致
  • 生成 CloudFront 签名 URL 时性能缓慢

    我正在按照此示例使用 PHP 在 CloudFront 上创建签名 URLhttp docs aws amazon com AmazonCloudFront latest DeveloperGuide CreateURL PHP html
  • 等待 JavaScript 中 Json 调用完成

    我正在使用下面的json调用在我的 javascript 方法中 function go123 var cityName var temp getJSON https abc in api city callback args functi
  • 如何检索 jquery $.ajax 对象的responseJSON属性[重复]

    这个问题在这里已经有答案了 我有这个 JavaScript ajax ajax type GET url DBConnect php data dataType json success function data error functi
  • 从 JavaScript 中 Firebase 数据库的查询结果中获取特定子项的值

    我在 Firebase 上有这个示例数据库 样本数据库 我有一个index html 其中有这两个输入文本 div class login form h2 Login Form h2 div
  • 对过期会话进行休息调用:HTTP 401 响应导致浏览器显示登录窗口

    我编写了一个 HTML 5 应用程序 它使用 AngularJS 并与在 Tomcat 上运行的 Java REST 后端进行交互 我使用 Spring Security 来处理登录和安全性 当用户进入网站时 他将被转发到登录页面 该页面创
  • 从 Cox PH 模型预测概率

    我正在尝试使用 cox 模型来预测时间 称为停止 3 后失败的概率 bladder1 lt bladder bladder enum lt 5 coxmodel coxph Surv stop event rx size number cl
  • 界面与组合

    我想我理解接口和抽象之间的区别 抽象设置默认行为 在纯抽象的情况下 行为需要由派生类设置 接口是您所需要的 无需基类的开销 那么接口相对于组合的优势是什么 我能想到的唯一优点是在基类中使用受保护的字段 我缺少什么 你的标题没有意义 你的解释
  • @NotNull.List 的目的

    当我查看标准时限制条件 http docs oracle com javaee 6 api javax validation constraints package summary html在 Bean Validation API JSR
  • iphone navigationController :在退出当前视图之前等待 uialertview 响应

    我有一个带有由导航控制器管理的后退按钮的视图 我想在用户单击后退按钮时检查文件是否已保存 如果文件已保存 您将返回到上一个视图 否则 uialertview 会询问您是否要保存文件 所以我这样做了 但视图消失了 然后警报视图出现了 void
  • 需要哈希表和数组列表

    我正在尝试在我的 Windows 7 Phone 应用程序中使用其他人的 C 类 这些类使用 Hashtable 类型的对象 有问题的文件有 using System Collections 在顶部 所以我假设这就是它想要的 Hashtab
  • 网站地址 URL 更改后,Wordpress 中未显示很棒的字体图标

    对于那些比我更精通编码的人来说 这可能是一个明显的问题 但我在 WordPress 中创建了一个网站 但他们的域名托管在其他地方 他们更改了 A 名称 现在它指向该网站 但字体很棒的图标现在是方框 我怎样才能解决这个问题 有简单的方法吗 非
  • Assert.Are Equal 和 Assert.AreSame 之间的区别?

    有什么区别断言 AreEqual and 断言 AreSame 这意味着 AreSame 检查它们是否是完全相同的对象 如果引用指示内存中的同一对象 AreEqual 检查对象是否具有相同的类型和值 相同的对象可以存在于内存中的两个不同位置
  • 设置存储在 Blob 上的媒体文件的内容类型

    我们有一个托管在 Azure 上的网站 它是基于媒体的 我们使用 JWPlayer 通过 HTTP 伪流来播放媒体 媒体文件以 3 种格式存储在 blob 上 mp4 ogg webm 问题是所有类型的媒体文件的内容类型都设置为应用程序 八
  • 通过鼻子测试检查某个函数是否发出警告

    我正在使用编写单元测试nose http somethingaboutorange com mrl projects nose 0 11 2 我想检查函数是否引发警告 该函数使用warnings warn 这是很容易就能做到的事情吗 def
  • 批量请求 - Dynamics CRM

    All 我正在尝试使用以下源代码对 Dynamics CRM 实施批量请求 public async Task
  • C# - 如何进行 HTTP 调用

    我想对网站进行 HTTP 调用 我只需要点击 URL 不想上传或下载任何数据 最简单 最快的方法是什么 我尝试了下面的代码 但它很慢 并且在第二次重复请求后 它只是超时 59 秒 然后恢复 WebRequest webRequest Web
  • 如何设置上拉刷新SwipeRefreshLayout

    我看到很多 ListView 下拉刷新的库 但是当从上到下拉动时它们是工作的 但是从下到上拉动时我如何刷新 我可以用这个做吗滑动刷新布局 http developer android com reference android suppor
  • NodeJS 内存增长 - (系统)内存泄漏?

    我在我们的生活环境中遇到了奇怪的内存泄漏 其中 system 堆中的对象不断增长 堆转储 Here is a memory dump where the memory usage grew to 800MB 请注意 该内存保留在Genera
  • C# 系统 CPU 使用情况并与 Windows 任务管理器同步

    这是一个由两部分组成的问题 我想将我的代码发布到堆栈上以帮助其他人完成相同的任务 问题一 我有一个代码子集 我相信它可以根据测量间隔正确测量 CPU 使用情况 根据检索的时间跨系统中的尽可能多的核心 我在线程调用中使用 1 秒 我必须从网上