C# 定时器 Timer 如何精确到 1-2 毫秒以内

最近在排查项目OTA的一个问题,触发了一毫秒或者2毫秒执行一次进程间通信的,导致通信阻塞的问题。这样就需要用到模拟触发1ms或者2ms触发事件。这让我第一时间想到了C#的定时器。由于我们项目用到的框架是基于.NETFramwork4.8的,所以我就建立了一个.NETFramwork4.8的WPF Demo 去验证

 private Timer timer;

 private void TimerTest_OnClick(object sender, RoutedEventArgs e)
 {
     timer = new Timer();
     timer.Interval = 1;
     timer.Elapsed += Timer_Elapsed;
     timer.Start();
 }

 private void Timer_Elapsed(object? sender, ElapsedEventArgs e)
 {
     Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"));
 }

Demo很简单, 就是创建一个按钮,创建一个System.Timers.Timer,点击后执行,,但是执行结果,却是要等待10+ms,跟我们设置的1ms的间隔不符合

 于是乎我查阅了一番资料:c# - Thread.Sleep(1) 耗时超过 1ms_Stack Overflow中文网

其实这跟PC的时钟相关,具体我就不解释了,详看上面链接的说明

 

我还不死心,会不会跟Dotnet的版本有关呢?

于是乎,我又创建了一个.Net8的 WPF的应用,用了如上一样的代码,也是用到了 相同命名空间的Timer

using Timer = System.Timers.Timer;

测试的结果,发现竟然可以精确到1-2ms的误差之内

 

这应该是微软对.Net8.0的 Timer 定时器做了优化了。

 

接下来如何在.NETFramwork4.8的环境下,实现精确度在1-2ms的定时执行了,只能自己写一个自旋的定时器,通过判断时间的间隔方式执行检测。

private CancellationTokenSource tokenSource = new CancellationTokenSource();

private void SelfAutoTimer()
{
    Task.Run(() =>
    {
        var current = DateTime.Now;

        while (!tokenSource.IsCancellationRequested)
        {
            var temp = DateTime.Now;
            if ((temp - current).TotalMilliseconds >=1)
            {
                Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"));
                current = temp;
            }
        }
    });
}

测试的结果跟.Net8.0的Timer的效果一样的,精确度在1-2ms之内

 

接下来的项目应该都需要往.Net8里边迁移才行了,可以减少很多不必要的工作量。

 

posted @ 2024-09-01 10:17  wuty007  阅读(166)  评论(2编辑  收藏  举报