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

如何在不占用过多CPU的情况下捕获每一个新的毫秒数

解决方案建议

问题根源

  • 空while(true)循环会让线程持续抢占CPU时间片,直接导致CPU使用率飙升。
  • Thread.Sleep(1)的精度受系统定时器分辨率限制(Windows默认约15.6ms),实际休眠时长往往大于1ms,因此会跳过大量毫秒数。

可行方案

方案1:高分辨率定时器+自旋等待

利用Stopwatch获取高精度时间,循环检测当前毫秒是否更新,避免无效休眠的同时保证响应速度:

long lastMS = GetMilliseconds();
Stopwatch sw = Stopwatch.StartNew();

while (true)
{
    long currentMS = GetMilliseconds();
    if (currentMS != lastMS)
    {
        Writer(currentMS);
        Console.WriteLine(currentMS);
        lastMS = currentMS;
    }
    // 短时间自旋等待,降低CPU占用的同时保证毫秒级响应
    Thread.SpinWait(10);
}
  • 优点:精度高,能捕获每一次毫秒变化;SpinWait比空循环CPU占用低,适合对精度要求极高的场景。
  • 缺点:仍会占用一定CPU资源,不适合长时间后台运行的低功耗场景。

方案2:调整系统定时器分辨率+精准休眠

Windows系统默认定时器分辨率约15.6ms,可通过API调整至1ms,再计算剩余时间精准休眠,避免跳过毫秒:

// 导入Windows API调整定时器分辨率
[DllImport("winmm.dll")]
static extern uint timeBeginPeriod(uint uPeriod);
[DllImport("winmm.dll")]
static extern uint timeEndPeriod(uint uPeriod);

// 初始化时设置1ms分辨率
timeBeginPeriod(1);

try
{
    long lastMS = GetMilliseconds();
    while (true)
    {
        long currentMS = GetMilliseconds();
        Writer(currentMS);
        Console.WriteLine(currentMS);
        
        // 计算到下一个毫秒的剩余时间,精准休眠
        long nextMS = currentMS + 1;
        long waitTime = nextMS - GetMilliseconds();
        if (waitTime > 0)
        {
            Thread.Sleep((int)waitTime);
        }
        lastMS = currentMS;
    }
}
finally
{
    // 程序结束时恢复系统原分辨率
    timeEndPeriod(1);
}
  • 优点:CPU占用低,调整分辨率后Sleep精度大幅提升。
  • 缺点:依赖Windows平台API,全局修改系统定时器分辨率可能增加系统功耗。

方案3:Windows平台高分辨率定时器回调

利用Windows的CreateTimerQueueTimerAPI实现毫秒级回调,无需手动循环等待:

[DllImport("kernel32.dll")]
static extern bool CreateTimerQueueTimer(out IntPtr phNewTimer, IntPtr TimerQueue, WaitOrTimerCallback Callback, IntPtr Parameter, uint DueTime, uint Period, uint Flags);

[DllImport("kernel32.dll")]
static extern bool DeleteTimerQueueTimer(IntPtr TimerQueue, IntPtr Timer, IntPtr CompletionEvent);

// 每1ms触发一次的回调函数
static void TimerCallback(IntPtr param, bool timerOrWaitFired)
{
    long currentMS = GetMilliseconds();
    Writer(currentMS);
    Console.WriteLine(currentMS);
}

// 初始化定时器
IntPtr timer;
CreateTimerQueueTimer(out timer, IntPtr.Zero, TimerCallback, IntPtr.Zero, 0, 1, 0);

// 保持程序运行
Console.ReadLine();

// 程序结束时清理定时器
DeleteTimerQueueTimer(IntPtr.Zero, timer, IntPtr.Zero);
  • 优点:CPU占用极低,由系统调度定时器,无需手动循环;精度有保障。
  • 缺点:仅支持Windows平台,需处理定时器的创建与清理逻辑。

额外注意事项

  • 如果Writer是同步写入文件,IO操作可能阻塞时间检测,建议改用异步写入(如File.AppendAllTextAsync)或批量写入,避免拖慢毫秒捕获节奏。
  • Linux/macOS平台可使用clock_nanosleep等API实现类似高精度等待逻辑。

内容的提问来源于stack exchange,提问作者Mansour Fahad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 23:07:11