起首简朴引见一下timer,这里所说的timer是指的System.Timers.timer,望文生义,就是可以在指定的距离是激发事宜。官方引见在这里,摘抄以下:
Timer 组件是基于效劳器的计时器,它使您可以指定在运用顺序中激发 Elapsed 事宜的周期性距离。然后可经由过程处置惩罚这个事宜来供应通例处置惩罚。 比方,假定您有一台关键性效劳器,必需每周 7 天、天天 24 小时都坚持运转。 可以建立一个运用 Timer 的效劳,以按期搜检效劳器并确保体系开启并在运转。 假如体系不响应,则该效劳可以尝试重新启动效劳器或关照管理员。 基于效劳器的 Timer 是为在多线程环境顶用于辅佐线程而设想的。 效劳器计时器可以在线程间挪动来处置惩罚激发的 Elapsed 事宜,如许就可以比 Windows 计时器更准确地定时激发事宜。
那运用这个计时器有啥优点呢?重要由于它是经由过程.NET Thread Pool完成的、轻量、计时准确、对运用顺序及音讯没有迥殊的请求。
Timer是怎样运用的之前有写过这篇:C# System.Timers.Timer定时器的运用和定时自动清算内存运用
什么叫重入呢?这是一个有关多线程编程的观点:顺序中,多个线程同时运转时,就可能发作同一个要领被多个历程同时挪用的状况。当这个要领中存在一些非线程平安的代码时,要领重入会致使数据不一致的状况。Timer要领重入是指运用多线程计时器,一个Timer处置惩罚还没有完成,到了时刻,另一Timer还会继承进入该要领举行处置惩罚。
关于定时器的重入题目处理要领尝试以下:
1、运用锁lock(Object)的要领来防备重入,示意一个Timer处置惩罚正在实行,下一个Timer发作的时刻发明上一个没有实行完就守候实行,实用重入很少涌现的场景。在触发的要领中到场lock,如许当线程2进入触发的要领中,发明已被锁,会守候锁中的代码处置惩罚完在实行,代码以下:
private static System.Timers.Timer aTimer = new System.Timers.Timer(); private static object loker=new object(); /// <summary> /// 设置定时器 /// </summary> public static void SetTimer() { //读取设置时刻 try { aTimer.Interval = 30000; aTimer.Elapsed += new System.Timers.ElapsedEventHandler(OnTimedEvent); aTimer.AutoReset = true;//每到指定时刻Elapsed事宜是到时刻就触发 aTimer.Enabled = true; //指导 Timer 是不是应激发 Elapsed 事宜。 } catch (Exception ex) { LogManager.RecordLog(LogType.Error, "ipad数据同步失足:" +ex.Message,ex); } } private static void OnTimedEvent(Object source, ElapsedEventArgs e) { //假如当前时刻是为设置的准点时刻就进来 var time =Convert.ToInt32( SynchronousHelper.AppConfig.get_Items("SycTime")); if (DateTime.Now.Hour == time && DateTime.Now.Minute == 0) { //lock,如许当线程2进入触发的要领中,发明已被锁,会守候锁中的代码处置惩罚完在实行 lock (loker) { LogManager.RecordLog(LogType.Info, "数据最先同步时刻:" + e.SignalTime, null); SetTimerStart(); System.Threading.Thread.Sleep(60000); //实行完超出当前分钟,使整点内只能进来一次 } } }
2.置一个标志,示意一个Timer处置惩罚正在实行,下一个Timer发作的时刻发明上一个没有实行完就摒弃(注重这里是摒弃,而不是守候哦,看看实行效果就邃晓啥意思了)实行,实用重入经常涌现的场景。在多线程下给inTimer赋值不够平安,Interlocked.Exchange供应了一种轻量级的线程平安的给对象赋值的要领(觉得比较高上大,也是比较引荐的一种要领)。
private static System.Timers.Timer aTimer = new System.Timers.Timer(); private static int inTimer = 0; /// <summary> /// 设置定时器 /// </summary> public static void SetTimer() { //读取设置时刻 try { aTimer.Interval = 30000; //半分钟触发一次 aTimer.Elapsed += new System.Timers.ElapsedEventHandler(OnTimedEvent); aTimer.AutoReset = true;//每到指定时刻Elapsed事宜是到时刻就触发 aTimer.Enabled = true; //指导 Timer 是不是应激发 Elapsed 事宜。 } catch (Exception ex) { LogManager.RecordLog(LogType.Error, "ipad数据同步失足:" +ex.Message,ex); } } private static void OnTimedEvent(Object source, ElapsedEventArgs e) { //假如当前时刻是为设置的准点时刻就进来 var time =Convert.ToInt32( SynchronousHelper.AppConfig.get_Items("SycTime")); if (DateTime.Now.Hour == time && DateTime.Now.Minute == 0) { //inTimer设置一个标志,示意一个Timer处置惩罚正在实行,下一个Timer发作的时刻发明上一个没有实行完就摒弃 if (Interlocked.Exchange(ref inTimer, 1) == 0) { LogManager.RecordLog(LogType.Info, "数据最先同步时刻:" + e.SignalTime, null); SetTimerStart(); System.Threading.Thread.Sleep(60000); //实行完守候超出当前分钟,使整点内只能进来一次 Interlocked.Exchange(ref inTimer, 0); } } }
轻微总结一下,timer是一个运用挺简朴的类,拿来即用,这里重要总结了运用timer时重入题目的处理,之前也没思考过这个题目,处理方案也挺简朴。这里的处理方案同时也实用多线程的重入题目。
以上就是C#中关于Timer定时器重入题目的处理要领的细致内容,更多请关注ki4网别的相干文章!