定时器间隔值较低
本文关键字:定时器 | 更新日期: 2023-09-27 17:49:32
我在c#(WPF)编程。我试着重复调用一个函数。i System.Timers
。当我尝试高值的计时器,如1秒= (1000ms),它工作良好,但当我尝试低值它不能工作。
为了显示问题所在,我使用了如下所示的代码:
Timer stopWatchTimer = new Timer();
int timerCounter = 0;
// this method called in button
private void StartStopWatch()
{
stopWatchTimer.Interval = 1;
stopWatchTimer.Elapsed += new ElapsedEventHandler(stopWatchTimerElapsed);
stopWatchTimer.Enabled = true;
}
private void stopWatchTimerElapsed(object sender, ElapsedEventArgs e)
{
timerCounter++;
Action a = () =>
{
// this is a Label
lblCounter.Content = timerCounter;
};
lblCounter.Dispatcher.Invoke(a);
if(timerCounter == 200)
{
stopWatchTimer.Enabled = false;
}
}
例如,我使用Label并将间隔设置为200毫秒。所以我的计时器应该停在1秒以内(1/5秒),但它花的时间太长了。问题在哪里?
定时器的间隔设置为1ms。Windows计时器没有那么高的准确性。在最好的情况下,Windows计时器的精度通常略高于8ms,这意味着你的计时器触发将在+-4 ms或更长时间之间的任何地方关闭。我通常尝试将计时器保持在最大100ms左右,并使用其他更准确的测量失效时间的方法(秒表)来增加计时累加器。
https://msdn.microsoft.com/en-us/library/system.timers.timer.interval%28v=vs.110%29.aspx
您使用Interval属性来确定触发Elapsed事件的频率。因为Timer类依赖于系统时钟,所以它具有与系统时钟相同的分辨率。这意味着,如果interval属性小于系统时钟的分辨率,则Elapsed事件将在由系统时钟分辨率定义的间隔内触发。下面的示例将Interval属性设置为5毫秒。当在系统时钟分辨率大约为15毫秒的Windows 7系统上运行时,该事件大约每15毫秒触发一次,而不是每5毫秒触发一次。
我制作了更精确的计时器,取决于系统滴答计数。
using System;
using System.ComponentModel;
namespace Timers
{
public class HandmadeTimer
{
private int interval = 100;
private bool enabled = false;
private BackgroundWorker BGW = new BackgroundWorker();
public HandmadeTimer(int interval)
{
this.interval = interval;
this.enabled = false;
this.BGW.WorkerSupportsCancellation = true;
this.BGW.DoWork += BGW_DoWork;
this.BGW.WorkerReportsProgress = true;
this.BGW.ProgressChanged += BGW_ProgressChanged;
}
public void Start()
{
if (!(enabled))
{
enabled = true;
BGW.RunWorkerAsync();
StartedEventHandler handler = Started;
if (!(handler == null))
handler();
}
}
public void Stop()
{
if (enabled)
{
enabled = false;
BGW.CancelAsync();
StoppedEventHandler handler = Stopped;
if (!(handler == null))
handler();
}
}
public bool Enabled
{
get { return this.enabled; }
set { if (value) Start(); else Stop(); }
}
public int Interval
{
get { return this.interval; }
set { if (value > 0) this.interval = value; }
}
private void BGW_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
long counter = Environment.TickCount + this.interval;
do
{
if (counter <= Environment.TickCount)
{
BGW.ReportProgress(100);
counter += this.interval;
}
} while (this.enabled);
}
private void BGW_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
ElapsedEventHandler handler = Elapsed;
if (!(handler == null))
handler();
}
public delegate void ElapsedEventHandler();
public event ElapsedEventHandler Elapsed;
public delegate void StartedEventHandler();
public event StartedEventHandler Started;
public delegate void StoppedEventHandler();
public event StoppedEventHandler Stopped;
}
}
更高效,更准确,且免费:p
我希望它有帮助!
用DispatcherTimer
代替timer
DispatcherTimer myTimer = new DispatcherTimer();
myTimer.Interval = TimeSpan.FromMilliseconds(1);
myTimer.Tick += myTimer_Tick;
所以myTimer_Tick
中的每件事都应该每1ms做一次。
- 请注意,如果您在
myTimer_Tick
中进行大量计算,则间隔将不准确。 - 也要注意,如果计算机很忙,它也会产生一些定时器延迟,但你可以玩
DispatcherPriority
让你的定时器先执行。