C#自己实现定时器

我们在写winfrom时经常会用到定时器,比如客户端通过socket定时向服务器发送检测包等。.netframework提供了一个定时器控件System.Windows.Forms.Timer,使用很方便。
 
其实通过C#多线程也可以实现定时器功能。我的做法大致为:新开一个线程用于计时,当时间间隔过后用事件timerover实现主窗体中的定时函数,再通过调用contro.invoke方法返回主窗体线程执行定时后的操作。
 
先定义两个类,timer类用于管理和配置定时器,interval_date用于计算两个时刻的间隔(例如2010年1月1日和2012年12月26日之间的毫秒),单位是毫秒,因此定时器的设置范围理论上可以无限大。原理不多说,下面放代码:

timer类代码:

    public class timer
    {
        int count = 0;
        public delegate void Deletimerover(int count);
        public event Deletimerover timerover;
        private int time;
        public int Time
        {
            set { time = value; }
            get { return time; }
        }
        private bool enable;
        public bool Enable
        {
            set { enable = value; }
        }
        public timer()
        {
        }
        public timer(int t)
        {
            time = t;
        }
        public void start_time()
        {
            Thread rd = new Thread(new ThreadStart(start));
            rd.IsBackground = true;
            count = 0;
            rd.Start();
        }
        private void start()
        {
            DateTime dt_tem = DateTime.Now;
            interval_date interval = new interval_date();
            while (interval.interval_millisec(dt_tem,DateTime.Now) < time) ;
            if (!enable)
            {
                return;
            }
            else
            {
                timerover(++count);
                start();
            }
        }
    }

interval_date类代码:

    public class interval_date
    {
        public long interval_millisec(DateTime dt1,DateTime dt2)
        {
            long interval = 0;
            interval += com_year(dt1,dt2);
            interval += com_month(dt1,dt2);
            interval += com_day(dt1,dt2);
            interval += com_hour(dt1, dt2);
            interval += com_minute(dt1, dt2);
            interval += com_second(dt1, dt2);
            interval += com_millisecond(dt1, dt2);
            return interval;
        }
        private long com_year(DateTime dt1, DateTime dt2)
        {
            int year1 = dt1.Year;
            int year2 = dt2.Year;
            long interval = 0;
            if (year1 != year2)
            {
                for (int i = year1 + 1; i < year2; i++)
                {
                    for(int j = 1; j <= 12; j++)
                    {
                        interval += DateTime.DaysInMonth(i, j);
                    }
                }
            }
            interval = interval * 24 * 3600 * 1000;
            return interval;
        }
        private long com_month(DateTime dt1, DateTime dt2)
        {
            int year1 = dt1.Year;
            int year2 = dt2.Year;
            int month1 = dt1.Month;
            int month2 = dt2.Month;
            long interval = 0;
            if (year1 != year2)
            {
                for (int i = month1 + 1; i <= 12; i++)
                {
                    interval += DateTime.DaysInMonth(year1, i);
                }
                for (int i = 1; i < month2; i++)
                {
                    interval += DateTime.DaysInMonth(year2, i);
                }
            }
            else
            {
                for (int i = month1+1; i < month2; i++)
                {
                    interval += DateTime.DaysInMonth(year1, i);
                }
            }
            interval = interval * 24 * 3600 * 1000;
            return interval;
        }
        private long com_day(DateTime dt1,DateTime dt2)
        {
            int year1 = dt1.Year;
            int year2 = dt2.Year;
            int month1 = dt1.Month;
            int month2 = dt2.Month;
            int day1 = dt1.Day;
            int day2 = dt2.Day;
            long interval = 0;
            if (year1 == year2 && month1 == month2)
            {
                if(day2 == day1)
                {
                    return 0;
                }
                interval = day2-day1-1;
            }
            else
            {
                interval += DateTime.DaysInMonth(year1, month1) - day1;
                interval += day2-1;
            }
            interval = interval * 24 * 3600 * 1000;
            return interval;
        }
        private long com_hour(DateTime dt1, DateTime dt2)
        {
            long interval = 0;
            if (dt1.Year == dt2.Year && dt1.Month == dt2.Month && dt1.Day == dt2.Day)
            {
                if (dt1.Hour == dt2.Hour)
                {
                    return 0;
                }
                interval += dt2.Hour - dt1.Hour - 1;
            }
            else
            {
                interval += 24 - dt1.Hour - 1;
                interval += dt2.Hour;
            }
            interval = interval * 3600 * 1000;
            return interval;
        }
        private long com_minute(DateTime dt1, DateTime dt2)
        {
            long interval = 0;
            if (dt1.Year == dt2.Year && dt1.Month == dt2.Month && dt1.Day == dt2.Day && dt1.Hour == dt2.Hour)
            {
                if (dt1.Minute == dt2.Minute)
                {
                    return 0;
                }
                interval += dt2.Minute - dt1.Minute - 1;
            }
            else
            {
                interval += 60 - dt1.Minute - 1;
                interval += dt2.Minute;
            }
            return interval * 60 * 1000;
        }
        private long com_second(DateTime dt1, DateTime dt2)
        {
            long interval = 0;
            if (dt1.Year == dt2.Year && dt1.Month == dt2.Month && dt1.Day == dt2.Day && dt1.Hour == dt2.Hour && dt1.Minute == dt2.Minute)
            {
                if (dt1.Second == dt2.Second)
                {
                    return 0;
                }
                interval += dt2.Second - dt1.Second - 1;
            }
            else
            {
                interval += 60 - dt1.Second - 1;
                interval += dt2.Second;
            }
            return interval * 1000;
        }
        private long com_millisecond(DateTime dt1, DateTime dt2)
        {
            long interval = 0;
            if (dt1.Year == dt2.Year && dt1.Month == dt2.Month && dt1.Day == dt2.Day && dt1.Hour == dt2.Hour && dt1.Minute == dt2.Minute && dt1.Second == dt2.Second)
            {
                interval += dt2.Millisecond - dt1.Millisecond;
            }
            else
            {
                interval += 1000 - dt1.Millisecond;
                interval += dt2.Millisecond;
            }
            return interval;
        }
    }

最后是主窗体代码:

    public partial class Form1 : Form
    {
        public timer newtimer = new timer();
        delegate void Time(int count);
        public void TimeOver(int count)
        {
            labelX1.Text = count.ToString();
        }
        public Form1()
        {
            InitializeComponent();
            newtimer.Time = 1000;
            newtimer.timerover +=new timer.Deletimerover(newtimer_timerover);
        }
        void newtimer_timerover(int count)
        {
            Time dd = new Time(TimeOver);
            this.Invoke(dd, new object[] { count});
        }
        private void buttonX1_Click(object sender, EventArgs e)
        {
            buttonX1.Enabled = false;
            newtimer.Enable = true;
            newtimer.Time = int.Parse(textBoxX1.Text);
            newtimer.start_time();
        }
        private void buttonX2_Click(object sender, EventArgs e)
        {
            newtimer.Enable = false;
            buttonX1.Enabled = true;
            labelX1.Text = "0";
            textBoxX1.Text = "1000";
        }
    }

一个文本框两个按钮,按钮一用来开启定时器,按钮二用来复位。

通过简单的验证,这种方法和.netframework提供的timer控件实现的定时误差在个位数(毫秒),也可以尝试用更精确的方法来测试一下。

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值