C#中关于Timer定时器重入问题的解决方法
项目中用到了定时器随着服务启动作定时任务,按指定的准点时间定时执行相关操作,但是在指定准点时间内我只想让它执行一次,要避免重入问题的发生。
首先简单介绍一下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定时器重入问题的解决方法的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

当今人工智能(AI)技术的发展如火如荼,它们在各个领域都展现出了巨大的潜力和影响力。今天大姚给大家分享4个.NET开源的AI模型LLM相关的项目框架,希望能为大家提供一些参考。https://github.com/YSGStudyHards/DotNetGuide/blob/main/docs/DotNet/DotNetProjectPicks.mdSemanticKernelSemanticKernel是一种开源的软件开发工具包(SDK),旨在将大型语言模型(LLM)如OpenAI、Azure

如果你是一名.NET开发者,你必须意识到在交付高质量软件方面,优化功能和性能的重要性。通过熟练使用提供的资源并减少网站加载时间,你不仅为用户创造了愉快的体验,还能减少基础设施成本。

在高并发请求处理方面,.NETASP.NETCoreWebAPI性能优于JavaSpringMVC,原因包括:AOT提前编译,减少启动时间;更精细的内存管理,由开发人员负责分配和释放对象内存。

C#是一种现代、面向对象的编程语言,由微软开发并作为.NET框架的一部分。1.C#支持面向对象编程(OOP),包括封装、继承和多态。2.C#中的异步编程通过async和await关键字实现,提高应用的响应性。3.使用LINQ可以简洁地处理数据集合。4.常见错误包括空引用异常和索引超出范围异常,调试技巧包括使用调试器和异常处理。5.性能优化包括使用StringBuilder和避免不必要的装箱和拆箱。

C#.NET面试问题和答案包括基础知识、核心概念和高级用法。1)基础知识:C#是微软开发的面向对象语言,主要用于.NET框架。2)核心概念:委托和事件允许动态绑定方法,LINQ提供强大查询功能。3)高级用法:异步编程提高响应性,表达式树用于动态代码构建。

C#.NET依然重要,因为它提供了强大的工具和库,支持多种应用开发。1)C#结合.NET框架,使开发高效便捷。2)C#的类型安全和垃圾回收机制增强了其优势。3).NET提供跨平台运行环境和丰富的API,提升了开发灵活性。

C#.NETisversatileforbothwebanddesktopdevelopment.1)Forweb,useASP.NETfordynamicapplications.2)Fordesktop,employWindowsFormsorWPFforrichinterfaces.3)UseXamarinforcross-platformdevelopment,enablingcodesharingacrossWindows,macOS,Linux,andmobiledevices.
