我在c#(WPF)中编程。我试图重复调用一个函数。我System.Timers
。当我为计时器尝试高值时,例如1秒=(1000毫秒),它运行良好但是当我尝试低值时,它无法工作。
要显示问题所在,我使用了如下所示的代码:
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 ms。所以我的计时器应该停止不到1秒(1/5秒),但这需要太长时间。问题出在哪里?
答案 0 :(得分:1)
计时器的间隔设置为1毫秒。 Windows计时器没有那么高的准确性。在最佳情况下,Windows定时器通常具有略高于8ms的精度,这意味着您的定时器触发将在+ -4 ms或更长时间内关闭。我通常会尝试将我的计时器保持在最大约100毫秒,并使用其他方法测量更精确的时间(秒表)来增加我的计时累加器。
答案 1 :(得分:0)
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毫秒触发一次。
答案 2 :(得分:0)
我制作更精确的计时器取决于系统滴答计数。
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
我希望它有所帮助!
答案 3 :(得分:0)
使用DispatcherTimer
代替timer
DispatcherTimer myTimer = new DispatcherTimer();
myTimer.Interval = TimeSpan.FromMilliseconds(1);
myTimer.Tick += myTimer_Tick;
因此myTimer_Tick
中的所有操作应每1毫秒执行一次。
myTimer_Tick
中进行大量计算,则间隔将不准确。DispatcherPriority
来使计时器首先执行。