• C# 定时器定时不准确问题


    .NET Framework提供三种Timer


    Server Timers System.Timers.Timer
    Thread Timers System.Threading.Timer
    Windows Timers System.Windows.Forms.Timer

    其中Windows Timers只是提供了和以前的WinAPI 一样的Timer,仍然是基于消息,仍然是单线程, 会有不准时的现象

    其它两个就不同了,他们是基于线程池的Thread Pool,这样最大的好处在于,产生的时间间隔准确均匀。
    Server Timers 和 Thread Timers 的不同在于ServerTimers 是基于事件的,Thread Timers是基于回调函数

    我更喜欢Thread Timer,比较轻量级方便易用。


    思路


    但是这样的Timer也有问题,就是由于时多线程定时器,就会出现如果一个Timer处理没有完成,到了时间下一个
    照样会发生,这就会导致重入问题

    对付重入问题通常的办法是加锁,但是对于 Timer却不能简单的这样做,你需要评估一下

    首先Timer处理里本来就不应该做太需要时间的事情,或者花费时间无法估计的事情,比同远方的服务器建立一个网络连接,这样的做法尽量避免

    如果实在无法避免,那么要评估Timer处理超时是否经常发生,如果是很少出现,那么可以用lock(Object)的方法来防止重入
    如果这种情况经常出现呢?那就要用另外的方法来防止重入了

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

    1. static int inTimer = 0;
    2. public static void threadTimerCallback(Object obj)
    3. {
    4. if ( inTiemr == 0 )
    5. {
    6. inTimer = 1;
    7. Console.WriteLine("Time:{0}, \tThread ID:{1}", DateTime.Now, Thread.CurrentThread.GetHashCode());
    8. Thread.Sleep(2000);
    9. inTimer = 0;
    10. }
    11. }



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

     

    1. static int inTimer = 0;
    2. public static void threadTimerCallback(Object obj)
    3. {
    4. if ( Interlocked.Exchange(ref inTimer, 1) == 0 )
    5. {
    6. Console.WriteLine("Time:{0}, \tThread ID:{1}", DateTime.Now, Thread.CurrentThread.GetHashCode());
    7. Thread.Sleep(250);
    8. Interlocked.Exchange(ref inTimer, 0);
    9. }
    10. }

  • 相关阅读:
    一文带你体验MRS HetuEngine如何实现跨源跨域分析
    H3C IPV6地址配置实验
    网页抓取软件-免费网页自动采集抓取任意内容软件
    uniapp 下拉框数据回显的问题
    MybatisPlus打印sql语句
    盘点四大运营商的5G套餐亮点,国庆出游上车5G不用愁!
    python SO3 & so3 BCH近似计算
    解决iOS Retina屏幕0.5pt线宽颜色失真问题
    Python中文件操作(IO流)及文件备份
    给自己改改代码(python)(记录)
  • 原文地址:https://blog.csdn.net/qq_36683522/article/details/132919296