Linux平台.NET 8.0环境下高精度固定定时器方案咨询
高精度跨平台.NET定时器解决方案(针对Raylib游戏项目)
问题描述
我正尝试为C# Raylib游戏项目实现一款高精度固定定时器,使其独立于游戏主绘制循环按固定间隔运行。当前使用System.Timers.Timer实现,但精度不足,间隔波动约±15ms。我在NuGet找到PrecisionTimer.NET库,但其不支持Linux平台(依赖winmm.dll),集成时报错。现咨询:是否有支持Linux .NET 8.0的同类库?或仅依赖系统库、带事件回调的定时器实现?
当前实现代码:
using System.Diagnostics; using System.Timers; namespace Engine { partial class Game { /*For calculating tick delta*/ static public double TickDelta; static private double SecondTick; static private Stopwatch? TickWatch; /*For calculating tick delta*/ private static readonly System.Timers.Timer GameTick = new(40); public static void InitTick() { GameTick.Elapsed += Tick; GameTick.Start(); TickWatch = new Stopwatch(); TickWatch.Start(); } public static void TerminateTick() { GameTick.Stop(); } public static void Tick(object? sender, ElapsedEventArgs e) { TimeSpan ts = TickWatch!.Elapsed; double ft = ts.TotalMilliseconds; TickDelta = ft - SecondTick; SecondTick = ts.TotalMilliseconds; } } }
解决方案
一、跨平台高精度定时器库推荐
- Nito.AsyncEx:提供的
AsyncPeriodicTimer基于.NET底层API实现,跨平台支持Linux/Windows/macOS,兼容.NET 8,精度远高于System.Timers.Timer,API风格贴近原生定时器,替换现有代码成本低。 - DotNetCross.Timers:轻量级跨平台定时器库,无平台特定依赖,支持高精度定时任务,适配游戏场景下的固定间隔触发需求。
二、纯系统库实现的自定义高精度定时器
若不想引入第三方库,可基于Stopwatch和后台线程实现无依赖的高精度定时器,Linux下通常能把间隔波动控制在1ms以内。
实现代码如下:
using System.Diagnostics; using System.Threading; namespace Engine { partial class Game { // 保留原有TickDelta计算字段 static public double TickDelta; static private double _lastTickTimeMs; static private readonly Stopwatch _tickWatch = Stopwatch.StartNew(); private static Thread? _timerThread; private static volatile bool _isRunning; private static readonly int _targetIntervalMs = 40; // 目标触发间隔 public static void InitTick() { _isRunning = true; _lastTickTimeMs = _tickWatch.Elapsed.TotalMilliseconds; // 启动高优先级后台线程 _timerThread = new Thread(RunTimerLoop) { IsBackground = true, Priority = ThreadPriority.Highest }; _timerThread.Start(); } public static void TerminateTick() { _isRunning = false; _timerThread?.Join(); } private static void RunTimerLoop() { while (_isRunning) { var currentTimeMs = _tickWatch.Elapsed.TotalMilliseconds; var elapsedSinceLastTick = currentTimeMs - _lastTickTimeMs; // 计算等待时长,组合Sleep+SpinWait平衡精度与CPU占用 var waitMs = _targetIntervalMs - elapsedSinceLastTick; if (waitMs > 1) { Thread.Sleep((int)waitMs - 1); } // 自旋等待剩余小间隔,避免Sleep的精度损耗 while (_tickWatch.Elapsed.TotalMilliseconds - _lastTickTimeMs < _targetIntervalMs) { Thread.SpinWait(100); } // 更新TickDelta并触发业务逻辑 currentTimeMs = _tickWatch.Elapsed.TotalMilliseconds; TickDelta = currentTimeMs - _lastTickTimeMs; _lastTickTimeMs = currentTimeMs; TickInternal(); } } // 迁移原Tick方法的业务逻辑到此处 private static void TickInternal() { // 放置游戏逻辑更新、状态同步等业务代码 } } }
实现说明
- 采用后台线程循环+Stopwatch高精度计时,通过
Thread.Sleep处理长等待、Thread.SpinWait处理短间隔的组合方式,在保证精度的同时避免CPU空转。 - 将线程优先级设为
Highest,降低系统调度对定时器触发时机的影响。 - 完全基于.NET系统库,无第三方依赖,跨Windows/Linux/macOS平台,完美兼容.NET 8。
内容的提问来源于stack exchange,提问作者Boyfinn
相关产品推荐
相关产品推荐

