C#自己编写定时器

来源:互联网 发布:linux中的解压缩命令 编辑:程序博客网 时间:2024/06/07 02:56


我们在写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 0
原创粉丝点击