C#定时器

1.单线程的定时器存在很多问题,定时器只是定时把消息WM_TIMER访到线程的消息队列里,但并不保证消息会立即被响应,如果碰巧系统比较忙,消息可能会在队列里放一段时间才被响应,这样会造成本来应该间隔一段时间发生的消息连续发生了。
2. 。NET FrameWork带来了新的解决方案
 Server TimersSystem.Timers.Timer基于服务器的计时器,位于"工具箱"的“组件”选项卡上
 Thread TimersSystem.Threading.Timer在编程时使用的线程计时器
 Windows TimersSystem.Windows.Forms.Timer基于 Windows 的标准计时器,"工具箱"的"Windows 窗体"选项卡上;
  • 区别a
    Windows Timers 提供了和WinAPI一样的Timer 基于消息,仍然是单线程
    其他两个是是基于线程池的Thread Pool【最大好处,产生的时间准确均匀】
  • 区别b
    Server Timers  和 Thread Timers 的不同在于ServerTimers 是基于事件的,Thread Timers是基于回调函数

Thread Timer是一个轻量级的方便使用,但也要注意一些问题,由于是多线程定时器,就会出现如果一个Timer处理没有完成,到了时间下一个照样会发生,导致严重错误,对付重入问题,通常的办法是加锁,但对于Timer不能简单的这样处理。

使用Timer来处于的事情,要注意:

首先Timer处理里本来就不应该做太需要时间的事情,或者花费时间无法估计的事情,比同远方的服务器建立一个网络连接,这样的做法尽量避免
如果实在无法避免,那么要评估Timer处理超时是否经常发生,如果是很少出现,那么可以用lock(Object)的方法来防止重入
如果这种情况经常出现呢?那就要用另外的方法来防止重入了

我们可以设置一个标志,表示一个Timer处理正在执行,下一个Timer发生的时候发现上一个没有执行完就放弃执行

static  int inTimer = 0;
public static void threadTimerCallback(Object obj)
{
     if ( inTiemr == 0 )
    {
         inTimer = 1;        

         Console.WriteLine("Time:{0}, /tThread ID:{1}", DateTime.Now, Thread.CurrentThread.GetHashCode());
         Thread.Sleep(2000);

         inTimer = 0;
      }
}

但是在多线程下给inTimer赋值不够安全,还好Interlocked.Exchange提供了一种轻量级的线程安全的给对象赋值的方法

 static int inTimer = 0;
 public static void threadTimerCallback(Object obj)
 {
       if ( Interlocked.Exchange(ref inTimer, 1) == 0 )
      {
           Console.WriteLine("Time:{0}, /tThread ID:{1}", DateTime.Now, Thread.CurrentThread.GetHashCode());
           Thread.Sleep(250);

           Interlocked.Exchange(ref inTimer, 0);
      }
 }

====试验=======================================================
1.ThreadTimer = new System.Threading.Timer(new TimerCallBack(onTime),this,0,1000)
 [- 参数 -]
  a.回调方法,
  b.回调方法中使用信息的对象,
  c.表示在 callback 参数调用它的方法之前延迟的时间量。指定 -1 毫秒以防止启动计时器。指定零 (0) 以立即启动计时器。
  d.在调用 callback 所引用的方法之间的时间间隔。指定 -1 毫秒可以禁用定期终止
 
2.

来源:(http://blog.sina.com.cn/s/blog_4b4c258701000649.html) - C#定时器_半糖主义_新浪博客

BaseTimeHandler 自定义一个事件
 
void OnTime(Object State)
{
   Control ctl = State as Form1;
   
   if ( ctl != null && BaseTimeHandler != null)
   {
    if ( ctl.IsHandleCreated )
    {
     DateTime dt = DateTime.Now; 
     String DateString = dt.ToString("yyyy/MM/dd");
     String TimeString = dt.ToString("HH:mm:ss");
   
     string[] args = new string[]{DateString,TimeString};    
     try
     {
      //如果在不同线程中
      if ( ctl.InvokeRequired )
       ctl.Invoke(BaseTimeHandler,args);
      else
       BaseTimeHandler(DateString,TimeString);
     }
     catch(Exception e)
     { }
    }
   }   
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值