如何在不占用过多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
相关产品推荐
相关产品推荐

