You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中如何基于系统空闲时间计算用户活动时长百分比

问题根因

现有代码存在两个核心错误,无法完成目标统计逻辑:

  1. 对TimeSpan结构字段理解偏差:IdleTime.Seconds是空闲时长扣除整分钟后剩余的秒数(取值范围0-59),IdleTime.Minutes是扣除整小时后剩余的分钟数(取值范围0-59),二者做大小比较无实际业务意义。
  2. 缺少时间片切分、空闲时长累计核心逻辑,未处理连续空闲场景的重复计数问题:如果直接累加每秒读取的IdleTime.Seconds,连续空闲120秒时会得到0+1+2+...+119的错误累计值,远大于实际空闲时长。
实现逻辑

要完成按时间片统计、计算活动占比的需求,按以下逻辑实现即可:

  • 定义固定配置:单时间片长度、总统计时间片数量
  • 以1秒为间隔采样,每一秒判断当前是否处于空闲状态(空闲时长大于等于1秒即判定当前秒为空闲),累计当前时间片的空闲秒数
  • 到达单个时间片边界时,将当前片的空闲秒数累加到总空闲计数变量Count中,重置当前片计数,开启下一个时间片统计
  • 所有时间片统计完成后,按对应公式计算活动占比
可直接运行的修正代码
using System;
using System.Runtime.InteropServices;
using System.Threading;

namespace MyMonitor
{
    class Program
    {
        static void Main()
        {
            // 统计配置
            const int timeSliceLength = 60; // 单个时间片长度:60秒
            const int totalSlices = 2; // 总统计时间片数:2个,合计120秒
            long Count = 0; // 存储累计总空闲秒数的变量
            DateTime currentSliceStart = DateTime.Now;
            int currentSliceIdle = 0;
            int finishedSlices = 0;

            while (finishedSlices < totalSlices)
            {
                TimeSpan idle = IdleTime;
                Console.WriteLine($"Last Input: {LastInput.ToShortTimeString()}");
                Console.WriteLine($"Idle for: {idle.TotalSeconds} Seconds");

                // 当前秒判定为空闲:空闲时长>=1秒,说明这1秒内无用户输入
                if (idle.TotalSeconds >= 1)
                {
                    currentSliceIdle++;
                }

                // 判断是否到达当前时间片边界
                double elapsedInSlice = (DateTime.Now - currentSliceStart).TotalSeconds;
                if (elapsedInSlice >= timeSliceLength)
                {
                    Count += currentSliceIdle;
                    Console.WriteLine($"当前时间片统计完成,本片空闲时长:{currentSliceIdle}秒");
                    // 重置状态开启下一片
                    finishedSlices++;
                    currentSliceStart = DateTime.Now;
                    currentSliceIdle = 0;
                }

                Thread.Sleep(TimeSpan.FromSeconds(1));
            }

            // 计算结果
            int totalDuration = timeSliceLength * totalSlices;
            long totalActiveSeconds = totalDuration - Count;
            double activeRatio = totalActiveSeconds * 100.0 / totalDuration;
            Console.WriteLine($"统计结束,总空闲时长:{Count}秒,总活动时长:{totalActiveSeconds}秒,总统计时长:{totalDuration}秒,活动占比:{activeRatio:F0}%");
            Console.ReadLine();
        }

        [DllImport("user32.dll", SetLastError = false)]
        private static extern bool GetLastInputInfo(ref Lastinputinfo plii);
        private static readonly DateTime SystemStartup = DateTime.Now.AddMilliseconds(-Environment.TickCount);

        [StructLayout(LayoutKind.Sequential)]
        private struct Lastinputinfo
        {
            public uint cbSize;
            public readonly int dwTime;
        }

        public static DateTime LastInput => SystemStartup.AddMilliseconds(LastInputTicks);

        public static TimeSpan IdleTime => DateTime.Now.Subtract(LastInput);

        private static int LastInputTicks
        {
            get
            {
                var lii = new Lastinputinfo { cbSize = (uint)Marshal.SizeOf(typeof(Lastinputinfo)) };
                GetLastInputInfo(ref lii);
                return lii.dwTime;
            }
        }
    }
}
代码说明
  • 变量Count即为要求的总空闲秒数累计变量,每结束一个时间片就会把该片的空闲值累加进去
  • 采样逻辑规避了连续空闲时的重复计数问题:每秒只判断当前这1秒是否属于空闲状态,不会累计连续增长的IdleTime值
  • 最终活动占比计算逻辑和示例完全匹配:两个60秒时间片分别累计活动45秒、30秒时,总活动时长75秒,计算得到活动占比为62%。

内容的提问来源于stack exchange,提问作者Nikhil Mahajan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 07:30:43