定时器间隔为低值

时间:2015-05-18 16:42:39

标签: c# wpf timer

我在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秒),但这需要太长时间。问题出在哪里?

4 个答案:

答案 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中进行大量计算,则间隔将不准确。
  • 还请注意,如果计算机很忙,它也会产生soeme计时器延迟,但是您可以使用DispatcherPriority来使计时器首先执行。