System.Timers.Timer定时器

   System.Timers.Timer是多线程定时器,如果在某个线程中一个Timer事件没有处理完成,到达下一个时间点,新的Timer同样会在另一个线程中被启动,这种多个线程中重复进入定时器事件处理函数的情况,就是重入。
     控制台显示的是运行定时器的当前线程ID,输出结果显示定时器在不同的线程运行。若将timeout方法中让当前线程休息400ms的代码去掉,你会发现这时定时器会在同一个线程中运行。
       为什么会这样呢?
这是因为,实例中的Timer会每隔200ms执行一次timeout方法,当前一次运行还没离开timeout方法时,Timer便会在新的线程中运行timeout方法。 若前次运行已经离开timeout方法,便会在同一个线程中继续运行timeout方法。
所以,Timer比较适合执行不太耗时的小任务,若在Timer中运行耗时任务,很容易出现由于超时导致的多线程重入问题,即多个线程同时进入timeout方法。
    为了应对多线程重入问题。可以加锁,也可以增加标志位。代码中红色部分则是,增加的标志位代码。
  如果当前有线程正在处理定时器事件,则标志位inTimer==1,其他线程无法进入;
  如果没有线程正在处理,则标志位inTimer==0,该线程可以进入,并将标志位置为 1,处理完成后,再将标志位置为 0.

    class Program
    {
          static System.Timers.Timer timer1 = new System.Timers.Timer(200);//实例化Timer类,设置间隔时间为 200 毫秒;
          static int inTimer = 0;
        static void Main(string[] args)
        {           
            timer1.Elapsed += new System.Timers.ElapsedEventHandler(timeout);  //到达时间的时候执行事件
            timer1.AutoReset = true;  //设置是执行一次(false)还是一直执行(true);     
            timer1.Enabled = true;    //是否执行System.Timers.Timer.Elapsed事件;          
             while (true) ;
        }
        static void timeout(Object source,System.Timers.ElapsedEventArgs e)
        {
            if (Interlocked.Exchange(ref inTimer,1) == 0)
            {
                  Thread.Sleep(400);
                  string currentThread = Thread.CurrentThread.ManagedThreadId.ToString();
                  Console.WriteLine(currentThread);
                  Interlocked.Exchange(ref inTimer,0);
            }
        }
    }

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值