如何让方法在每个循环周期结束前10秒精准触发?
问题根源
你现在的触发时间越来越早,核心原因是120秒周期结束后没有重置Stopwatch。举个例子:
- 第一次触发在累计110秒(1:50),没问题;到120秒时你停了timer和stopwatch,但没把stopwatch归零
- 第二次启动后,累计时间从120秒开始算,这时候220秒(3:40)的时候
220%110=0,就触发了——但你要的是第二个120秒周期的第110秒,也就是120+110=230秒(3:50),自然就提前了10秒 - 后面每次都会差10秒,触发时间越来越早
修正代码
给你两种靠谱的实现方式,选哪种都行:
方式1:周期结束重置计时器(推荐)
每次120秒到点后,把Stopwatch归零,这样每个周期的计时都是从零开始,判断110秒触发就准了:
private void OnTimerElapsed(object sender, ElapsedEventArgs e) { Application.Current.Dispatcher.BeginInvokeOnMainThread(() => { MainTimer.Text = stopwatch.Elapsed.ToString(@"hh\:mm\:ss"); double currentCycleSec = stopwatch.Elapsed.TotalSeconds; Tasklabel.Text = currentCycleSec.ToString(); // 触发周期内第110秒的操作(用误差范围避免浮点精度坑) if (Math.Abs(currentCycleSec - 110) < 0.1) { // 这里写你要触发的方法 // do sth } // 120秒周期结束,重置计时准备下一轮 if (currentCycleSec >= 120) { Value = false; stopwatch.Stop(); stopwatch.Reset(); // 关键:把计时器归零 timer.Stop(); // 如果需要自动开启下一个周期,解开下面的注释 // stopwatch.Start(); // timer.Start(); // 这里写周期结束要执行的操作 // do sth } }); }
方式2:不重置计时器,计算当前周期内的时间
要是不想重置Stopwatch,就用总时间对120取余,算出当前正处在这个120秒周期的第几秒,再判断是不是到110秒:
private void OnTimerElapsed(object sender, ElapsedEventArgs e) { Application.Current.Dispatcher.BeginInvokeOnMainThread(() => { MainTimer.Text = stopwatch.Elapsed.ToString(@"hh\:mm\:ss"); double totalSec = stopwatch.Elapsed.TotalSeconds; Tasklabel.Text = totalSec.ToString(); // 算出当前在这个120秒周期里的时间 double currentCycleSec = totalSec % 120; // 判断是否到周期内的110秒 if (Math.Abs(currentCycleSec - 110) < 0.1) { // 执行你的目标操作 // do sth } // 120秒周期结束的逻辑(取余后接近0就说明到点了) if (Math.Abs(currentCycleSec) < 0.1 && totalSec > 0) { Value = false; timer.Stop(); // 周期结束的操作 // do sth } }); }
重要提醒
- 别直接用
==判断浮点数相等!比如currentCycleSec == 110很可能因为计时精度问题判断失败,用Math.Abs(差值) < 0.1这种误差范围的方式更稳妥 - 确保你的Timer间隔设置合理,比如设成1000毫秒(每秒触发一次),这样判断的精度足够
- 如果需要循环执行120秒周期,记得在周期结束后重新启动Stopwatch和Timer
内容的提问来源于stack exchange,提问作者Marsjanin
相关产品推荐
相关产品推荐

