C# 持续增加时间间隔的System.Timers.Timer

C# 持续增加时间间隔的System.Timers.Timer,c#,timer,C#,Timer,我目前正在开发一个对时间敏感的程序,在这个程序中,我必须每秒读取一次设备的数据。 我目前正在为此使用计时器,但我发现时间稳定会增加间隔1毫秒。这可能会导致问题,因为程序将运行很长时间 Read Exe Time是代码执行所用的时间 在每个经过的事件开始时执行读取 我如何确保时钟不会增加,我可以理解滴答声可能不会精确到毫秒,但我一直在爬升似乎很奇怪。我的代码执行不需要整整1000毫秒,所以不是这样。16.6分钟后,读数将被推一整秒钟 Read Exe Time: 574.0637 ms Perfo

我目前正在开发一个对时间敏感的程序,在这个程序中,我必须每秒读取一次设备的数据。 我目前正在为此使用计时器,但我发现时间稳定会增加间隔1毫秒。这可能会导致问题,因为程序将运行很长时间

Read Exe Time
是代码执行所用的时间

在每个经过的事件开始时执行读取

我如何确保时钟不会增加,我可以理解滴答声可能不会精确到毫秒,但我一直在爬升似乎很奇怪。我的代码执行不需要整整1000毫秒,所以不是这样。16.6分钟后,读数将被推一整秒钟

Read Exe Time: 574.0637 ms
Performing reading: 22:58:39.696
Read Exe Time: 571.9422 ms
Performing reading: 22:58:40.697
Read Exe Time: 595.5333 ms
Performing reading: 22:58:41.697
Read Exe Time: 566.2602 ms
Performing reading: 22:58:42.698
Read Exe Time: 568.2275 ms
Performing reading: 22:58:43.698
Read Exe Time: 569.7573 ms
Performing reading: 22:58:44.700
Read Exe Time: 561.655 ms
Performing reading: 22:58:45.701
Read Exe Time: 567.8385 ms
Performing reading: 22:58:46.702
Read Exe Time: 584.8305 ms
Performing reading: 22:58:47.703
Read Exe Time: 588.754 ms
Performing reading: 22:58:48.703
Read Exe Time: 560.8154 ms
Performing reading: 22:58:49.704
Read Exe Time: 567.9324 ms
Performing reading: 22:58:50.705
Read Exe Time: 579.1354 ms
Performing reading: 22:58:51.706
Read Exe Time: 563.0227 ms
Performing reading: 22:58:52.707
Read Exe Time: 569.557 ms
Performing reading: 22:58:53.708
Read Exe Time: 560.707 ms
Performing reading: 22:58:54.708
Read Exe Time: 574.6268 ms
Performing reading: 22:58:55.709
Read Exe Time: 570.4872 ms
Performing reading: 22:58:56.710
Read Exe Time: 574.8388 ms
Performing reading: 22:58:57.710
Read Exe Time: 573.2054 ms
Performing reading: 22:58:58.710
Read Exe Time: 578.6189 ms
Performing reading: 22:58:59.711
Read Exe Time: 565.7442 ms
Performing reading: 22:59:0.711
Read Exe Time: 564.7523 ms
Performing reading: 22:59:1.712
Read Exe Time: 575.8134 ms
Performing reading: 22:59:2.713
Read Exe Time: 570.9416 ms
Performing reading: 22:59:3.713
Read Exe Time: 573.1493 ms
Performing reading: 22:59:4.714
Read Exe Time: 570.2831 ms
Performing reading: 22:59:5.714
Read Exe Time: 568.2672 ms
Performing reading: 22:59:6.715
Read Exe Time: 586.5607 ms
Performing reading: 22:59:7.715
Read Exe Time: 588.0465 ms
Performing reading: 22:59:8.715
Read Exe Time: 574.1118 ms
Performing reading: 22:59:9.716
代码

private void StartMeter()
{
    this.Meter.Start();

    this.ReadingTime = new Timer(1000);
    this.ReadingTime.Elapsed += new ElapsedEventHandler(PerformReading);
    this.ReadingTime.Start();
}

    private void PerformReading(object sender, ElapsedEventArgs e)
    {
        Console.WriteLine("Performing reading: " + DateTime.Now.Hour + ":" +  DateTime.Now.Minute + ":" +  DateTime.Now.Second + "." +  DateTime.Now.Millisecond);

        // Code here
    }
更新: 如果我只是将时间设置为999毫秒,它会稳定地减少吗

Performing reading: 23:4:50.527
Read Exe Time: 562.7729 ms
Performing reading: 23:4:51.527
Read Exe Time: 566.8178 ms
Performing reading: 23:4:52.527
Read Exe Time: 562.3829 ms
Performing reading: 23:4:53.526
Read Exe Time: 567.9165 ms
Performing reading: 23:4:54.526
Read Exe Time: 561.1329 ms
Performing reading: 23:4:55.525
Read Exe Time: 562.9359 ms
Performing reading: 23:4:56.525
Read Exe Time: 560.4151 ms
Performing reading: 23:4:57.524
Read Exe Time: 561.0302 ms
Performing reading: 23:4:58.524
Read Exe Time: 561.5756 ms
Performing reading: 23:4:59.524
Read Exe Time: 565.2936 ms
Performing reading: 23:5:0.523
Read Exe Time: 561.8903 ms
Performing reading: 23:5:1.523
Read Exe Time: 561.8768 ms
Performing reading: 23:5:2.523
Read Exe Time: 562.3904 ms
Performing reading: 23:5:3.523
Read Exe Time: 562.3363 ms
Performing reading: 23:5:4.523
Read Exe Time: 561.6288 ms
Performing reading: 23:5:5.523
Read Exe Time: 560.4596 ms
Performing reading: 23:5:6.522
Read Exe Time: 562.34 ms
Performing reading: 23:5:7.522
Read Exe Time: 561.5994 ms
Performing reading: 23:5:8.522
Read Exe Time: 561.6811 ms
Performing reading: 23:5:9.521
Read Exe Time: 561.7427 ms
Performing reading: 23:5:10.521
Read Exe Time: 561.8044 ms
Performing reading: 23:5:11.520
Read Exe Time: 561.6246 ms
Performing reading: 23:5:12.520
Read Exe Time: 560.5753 ms
Performing reading: 23:5:13.520
Read Exe Time: 563.8604 ms
Performing reading: 23:5:14.520
Read Exe Time: 562.2606 ms
Performing reading: 23:5:15.534
Read Exe Time: 560.8377 ms
Performing reading: 23:5:16.534
Read Exe Time: 560.4553 ms
Performing reading: 23:5:17.534
Read Exe Time: 562.5534 ms
Performing reading: 23:5:18.533
Read Exe Time: 563.0269 ms
Performing reading: 23:5:19.532
Read Exe Time: 561.2851 ms
Performing reading: 23:5:20.532
Read Exe Time: 560.3442 ms
Performing reading: 23:5:21.531
Read Exe Time: 561.5201 ms
Performing reading: 23:5:22.530
Read Exe Time: 560.609 ms
Performing reading: 23:5:23.530
编辑:针对@PeterLuu

Performing reading: 22:44:45.13
Performing reading: 22:44:45.449
Performing reading: 22:44:45.879
Performing reading: 22:44:46.320
Performing reading: 22:44:46.761
Performing reading: 22:44:47.192
Performing reading: 22:44:47.631
Performing reading: 22:44:48.74
Performing reading: 22:44:48.577
Performing reading: 22:44:49.49
Performing reading: 22:44:49.637
代码呢

private void StartMeter()
{
    DateTime now = DateTime.UtcNow;
    NextTickTimeWholeSeconds = new DateTime(now.Ticks - (now.Ticks % TimeSpan.TicksPerSecond), now.Kind);

    this.Meter.Start();

    this.ReadingTime = new Timer(1000);
    this.ReadingTime.Elapsed += new ElapsedEventHandler(PerformReading);
    this.ReadingTime.Start();
    ReadingTime.Interval = GetTimeToNextSecond();
}

private double GetTimeToNextSecond()
{
    NextTickTimeWholeSeconds = NextTickTimeWholeSeconds.AddSeconds(1);
    var interval = NextTickTimeWholeSeconds - DateTime.UtcNow;
    return interval.Milliseconds < 1 ? GetTimeToNextSecond() : interval.Milliseconds;
}

private void PerformReading(object sender, ElapsedEventArgs e)
{
    Console.WriteLine("Performing reading: " + DateTime.UtcNow.Hour + ":" + DateTime.UtcNow.Minute + ":" + DateTime.UtcNow.Second + "." + DateTime.UtcNow.Millisecond);

    // My code takes about 500-600 ms

    ReadingTime.Interval = GetTimeToNextSecond();
}
private void StartMeter()
{
DateTime now=DateTime.UtcNow;
nextticktimewisteconds=newdatetime(now.Ticks-(now.Ticks%TimeSpan.TicksPerSecond),now.Kind);
这个.Meter.Start();
this.ReadingTime=新定时器(1000);
this.ReadingTime.appeased+=新的ElapsedEventHandler(执行读取);
这是.ReadingTime.Start();
ReadingTime.Interval=gettimenextsecond();
}
私有双gettimextsecond()
{
nextticktimewisteconds=nextticktimewisteconds.AddSeconds(1);
var interval=nextticktimewitseconds-DateTime.UtcNow;
返回interval.millizes<1?getTimeOnextSecond():interval.millizes;
}
私有void执行读取(对象发送方,ElapsedEventArgs e)
{
控制台.WriteLine(“执行读取:“+DateTime.UtcNow.Hour+”:“+DateTime.UtcNow.Minute+”:“+DateTime.UtcNow.Second+”+“+DateTime.UtcNow.毫秒”);
//我的代码大约需要500-600毫秒
ReadingTime.Interval=gettimenextsecond();
}

不久前,使用CodingBarfield的回答对我来说非常有效


抱歉没有提供更多的细节,这里有很好的解释

您可以根据下一秒之前的时间(例如,如果点上下一秒之前只有890毫秒),并在每次迭代时以该间隔重新启动计时器,以防止漂移。根据Jared之前的回答改编。这并不能提供精确到毫秒的精度,但它可以防止你的时间漂移,而且事件总是“准时”发生

编辑:删除了一个不必要的行-实际上不需要调用Start()两次,只需更改间隔就足够了,因为更改间隔会重新启动计时器

编辑2:进行了一些更改,使其在边缘情况下更精确(例如,防止连续多次触发)


“时间稳定使间隔增加1 ms pr tick”可能我误解了,但听起来间隔没有增加或减少,它只是大约
1.001
0.999
s。是的,这是正确的,或者1.0000-1.0001可能更正确,你可能想要。而且可能不得不使用com调用。一个普通的计时器无论如何都不会给你这样的准确度。从DateTime.Now开始,每勾一次,重新校准一次。但是,当其他进程繁忙时,您仍然可能会有几个100毫秒的超限。您必须记住,您的机器运行不正常。计时器的精度非常高,在普通机器上无法再现这些结果。您机器上的另一个程序已重新编程定时器中断间隔。例如,Chrome就是这样做的。最好专注于从23:5:14.520到23:5:15.534的突然跳跃,这是正常的,也是你可以期待的。通过这次编辑,我得到了以下信息:执行读取:0:17:21.3执行读取:0:17:21.183执行读取:0:17:21.370执行读取:0:17:21.560执行读取:0:17:21.746执行读取:0:17:22.187执行读取:0:17:22.611执行读取:0:17:23.267执行读取:0:17:23.57执行读取:0:17:23.314执行读取:0:17:23.314抱歉,我更改了几次-您是否使用了我在那里发布的最新版本中的代码(其中函数名为GetTimeOneXTSecond)?是,我使用的是当前版本,我无法想象为什么它每秒执行一次以上——即使您只是使用类似于static void Main(string[]args){var meter=new meter();meter.StartMeter();System.Threading.Thread.Sleep(10000000);}的东西初始化代码,这种情况还会发生吗?@DoomStone你能把
ReadingTime.AutoReset=false
行放在你的代码中,看看它是否适合你吗?可能想检查System.Threading.Timer,因为我认为这是你参考答案使用的pinvoke的一个包装。
public class Meter
{
    private Timer ReadingTime;
    private DateTime NextTickTimeWholeSeconds;

    public Meter() {
        DateTime now = DateTime.UtcNow;
        NextTickTimeWholeSeconds = new DateTime(now.Ticks - (now.Ticks % TimeSpan.TicksPerSecond), now.Kind);

        ReadingTime = new Timer();
        ReadingTime.AutoReset = false;
        ReadingTime.Elapsed += new ElapsedEventHandler(PerformReading);
        ReadingTime.Interval = GetTimeToNextSecond();
    }

    public void StartMeter()
    {
        ReadingTime.Start();
    }

    private double GetTimeToNextSecond()
    {
        NextTickTimeWholeSeconds = NextTickTimeWholeSeconds.AddSeconds(1);
        var interval = NextTickTimeWholeSeconds - DateTime.UtcNow;
        return interval.Milliseconds < 1 ? GetTimeToNextSecond() : interval.Milliseconds;
    }

    private void PerformReading(object sender, ElapsedEventArgs e)
    {
        Console.WriteLine("Performing reading: " + DateTime.Now.Hour + ":" + DateTime.Now.Minute + ":" + DateTime.Now.Second + "." + DateTime.Now.Millisecond);
        ReadingTime.Interval = GetTimeToNextSecond();
    }
}
Performing reading: 18:11:47.10
Performing reading: 18:11:48.4
Performing reading: 18:11:49.10
Performing reading: 18:11:50.6
Performing reading: 18:11:51.9
Performing reading: 18:11:52.5
Performing reading: 18:11:53.10
Performing reading: 18:11:54.5
Performing reading: 18:11:55.9
Performing reading: 18:11:56.7
Performing reading: 18:11:57.7
Performing reading: 18:11:58.7
Performing reading: 18:11:59.7
Performing reading: 18:12:0.8
Performing reading: 18:12:1.7
Performing reading: 18:12:2.6

... about 50 seconds later ...

Performing reading: 18:12:50.1
Performing reading: 18:12:51.0
Performing reading: 18:12:52.0
Performing reading: 18:12:53.0
Performing reading: 18:12:53.999
Performing reading: 18:12:55.0
Performing reading: 18:12:56.0
Performing reading: 18:12:56.999
Performing reading: 18:12:58.0
Performing reading: 18:12:59.0
Performing reading: 18:13:0.0
Performing reading: 18:13:0.999
Performing reading: 18:13:2.0
Performing reading: 18:13:3.1
Performing reading: 18:13:4.0
Performing reading: 18:13:5.0
Performing reading: 18:13:6.0
Performing reading: 18:13:6.999
Performing reading: 18:13:8.0
Performing reading: 18:13:9.0
Performing reading: 18:13:10.0
Performing reading: 18:13:11.0
Performing reading: 18:13:12.1
Performing reading: 18:13:13.0
Performing reading: 18:13:13.999
Performing reading: 18:13:15.0
Performing reading: 18:13:16.0
Performing reading: 18:13:16.999
Performing reading: 18:13:18.0
Performing reading: 18:13:19.1
Performing reading: 18:13:20.0
Performing reading: 18:13:21.0
Performing reading: 18:13:21.999
Performing reading: 18:13:23.0
Performing reading: 18:13:24.0
Performing reading: 18:13:25.0
Performing reading: 18:13:26.0
Performing reading: 18:13:27.0
Performing reading: 18:13:28.0
Performing reading: 18:13:29.0