我想创建counter down,例如每隔10秒,程序将调用一个执行任务的方法。在我使用System.Windows.Forms.Timer和System.Timers.Timer之前,我得到的计数不准确。然后我尝试使用System.Diagnostics.Timer我已经读过这个功能非常准确。 这是我的示例代码
Stopwatch stopWatch = new Stopwatch();
private bool StartTrue = false;
...
private void StartProg_Click(object sender, EventArgs e)
{
StartTrue = true;
StartCounting();
}
private void StartCounting()
{
while(StartTrue)
{
stopWatch.Start();
while(stopWatch.Elapsed.Seconds < 1);
stopWatch.Stop();
stopWatch.Reset();
...
// this part the program for doing task every x second
}
}
我的程序挂起,cpu使用率很高。先生,我的错误在哪里?或者这样做的更好的方法是什么?
更新: 例如,我想每10秒钟将数据写入串行。当我使用winform计时器或system.timers
时10 2/6/2015 6:24:34 PM
9 2/6/2015 6:24:35 PM
8 2/6/2015 6:24:36 PM
7 2/6/2015 6:24:37 PM
6 2/6/2015 6:24:38 PM
5 2/6/2015 6:24:39 PM
4 2/6/2015 6:24:40 PM
3 2/6/2015 6:24:41 PM
2 2/6/2015 6:24:42 PM
1 2/6/2015 6:24:44 PM
10 2/6/2015 6:24:45 PM
计时器滴答是不准确的,在上面,最后一行是当计时器在第80秒触发时。
答案 0 :(得分:0)
单独使用Stopwatch
来衡量时间是低效的,因为您需要在Thread.Sleep
上运行busy wait或浪费线程资源。虽然短时间(10毫秒?)间隔可能需要忙碌等待,但您的情况(10秒)似乎并不需要。
计时器的频率远高于执行任务所需的频率,并检查&#34;正确的时间&#34;谈到。即100毫秒的计时器可能足够合理,每隔10秒就能完成一次#34;事件
从理论的角度来看,您需要以这样的方式设置频率,以便在误差范围内至少进行2次检查:即如果您需要10s +/- 0.1s,您的计时器应该至少每0.1s / 2触发一次0.05秒。如果你想进行花哨的采样 - 运行带有可变间隔的计时器 - 9s,0.1s,0.01s关闭你得到所需的时间。您可以从Nyquist–Shannon sampling theorem开始阅读正确的解释。
请注意,Window不是Real-Time-Operating-System,并且不保证任何特定线程有机会在特定时刻执行(即使对于具有更高优先级的线程)。因此,对于大多数与时间相关的操作,您应该预期相对较大的错误(我在相对自由系统上估计30-50ms开始),除非特别注意将其最小化。再过10秒间隔,这可能不是问题。
答案 1 :(得分:0)
谢谢大家。 我在代码中做了一点改动,暂时我会使用这段代码
Timer NewTimer;
int secval;
int tsecs;
...
secVal = int.Parse(BoxSecond.Text);
tsecs = secVal;
NewTimer= new Timer(1000);
NewTimer.Elapsed += NewCounter;
private void TStartStop_Click(object sender, EventArgs e)
{
...
NewTimer.Start();
}
private void NewCounter(Object source, ElapsedEventArgs e)
{
TimeNow= DateTime.Now;
if (TimeBefore != null)
{
if (TimeNow.Second - TimeBefore.Second == 2)
{
tsecs--;
...
//Invoke for label
}
else if (TimeNow.Second - TimeBefore.Second == 0)
{
tsecs++;
...
//Invoke for label
}
}
TimeBefore = DateTime.Now;
...
if(tsecs != 0)
{
tsecs--;
//Invoke for label
}
else if(tsecs == 0)
{
tsecs = secVal;
tsecs--;
//Invoke for label
}
}
比以前更准确