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控件实现的定时误差在个位数(毫秒),也可以尝试用更精确的方法来测试一下。



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值