C#计时器精度的探究

1.前言

  在与下位机(DSP6748)进行通信的时候,使用System.Timer.Timer进行计时,发现与下位机的时间不一致。实验证明,是使用System.Timer.Timer计时不准造成的。众所周知,System.Windows.Forms.Timer的计时是相对比较不准确的,所以,就System.Timer.Timer和System.Thread.Timer进行测试。
  
2.System.Timer.Timer

1分钟出现1秒的误差。
C#计时器精度的探究_第1张图片
7分钟误差6秒
C#计时器精度的探究_第2张图片
为了测试定时器运行是否被定时器中的任务所影响,在执行方法中使线程休眠10秒,即Thread.sleep(10000),影响了通过执行秒数计算出来的理论时间。可见,elapse方法中的执行,是会影响执行结果的。定时器没有开启一个独立的线程进行计时操作。
究其根源,是因为Windows是分时系统,不是实时系统。它是‘抢占式多任务(Preemptive mutitasking)’的系统。程序是否执行取决于系统调度的粒度,有可能在计时的时候,程序没有被分配到时间片。
代码:

using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {

        System.Timers.Timer Auto_ControlTimer = new System.Timers.Timer();                  DateTime StartTime = new DateTime();

        int Seconds = 0;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            StartTime = DateTime.Now;
            lbl_StartTime.Text = StartTime.ToString();

            Auto_ControlTimer.Enabled = true;
            Auto_ControlTimer.Interval = 1000;
            Auto_ControlTimer.Elapsed += new System.Timers.ElapsedEventHandler(Auto_ControlTimer_Elapsed);

        }

        void Auto_ControlTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            Thread.CurrentThread.IsBackground = true;
            Seconds++;
            if (this.InvokeRequired)
            {

                this.BeginInvoke(new Action(()=>{
                    lbl_AimTime.Text = StartTime.AddSeconds(Seconds).ToString();
                    lbl_RealTime.Text = DateTime.Now.ToString();
                }));
            }
        }


    }
}

3.System.Threading.Timer

仅使用Threading.Timer进行计时时,结果如下:
C#计时器精度的探究_第3张图片
采用新开线程进行计时,得到如下结果:
C#计时器精度的探究_第4张图片
可见,计时依然是不准确的。
代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {

        System.Threading.Timer Auto_ControlTimer ;//到起始时间自动启动定时器
        DateTime StartTime = new DateTime();

        int Seconds = 0;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            StartTime = DateTime.Now;
            lbl_StartTime.Text = StartTime.ToString();

            Thread t = new Thread(new ThreadStart(() =>
            {
                Auto_ControlTimer = new System.Threading.Timer(new TimerCallback(Auto_ControlTimer_Elapsed), null, 1000, 1000);
            })
            );
            t.IsBackground = true;
            t.Start();

        }

        void Auto_ControlTimer_Elapsed(object sender)
        {
            Seconds++;
            if (this.InvokeRequired)
            {

                this.BeginInvoke(new Action(()=>{
                    lbl_AimTime.Text = StartTime.AddSeconds(Seconds).ToString();
                    lbl_RealTime.Text = DateTime.Now.ToString();
                }));
            }

        }
    }

自己写的程序是站在自己的立场进行编写的,也许会看不到全面,所以在csdn上搜索了别人写的用System.Windows.Form.Timer时钟程序进行测试,排除因为个人原因造成的错误或者误差。实践证明,计时器1分钟存在1秒钟的误差。如下图:
C#计时器精度的探究_第5张图片

4.结论

  使用System.Windows.Forms.Timer,System.Timer.Timer和System.Threading.Timer计时时,运行时间过长之后,均会出现1分钟接近1秒的误差。因为Windows是分时系统,不是实时系统。它是‘抢占式多任务(Preemptive mutitasking)’的系统。程序是否执行取决于系统调度的粒度,有可能在计时的时候,程序没有被分配到时间片。要获取相对准确的时间,只能获取当前系统的时间,即DateTime.Now。

你可能感兴趣的:(c#,计时器精度)