C# Windows Service重复读取已处理记录,疑似内存未清除问题求助
问题排查:Windows Service重复读取已处理记录
我是Windows Service与C#开发新手,开发的Windows Service需读取数据库表数据,转为JSON后发送至外部接口,成功接收返回结果后更新本地标记以标识记录已处理。目前遇到的问题:定时器首次启动时能正确筛选未标记记录并处理;但定时器间隔运行时,仍会读取已处理的同批记录,疑似上一次运行的内存未被清除。
现有代码
OnStart方法
protected override void OnStart(string[] args) { try { log.Info("Starting the service"); T = new System.Timers.Timer(); T.Enabled = true; T.Elapsed += new ElapsedEventHandler(OnElapsedHandler); T.Interval = scheduledTime; } catch(Exception e) { log.info(e.message()); } }
OnElapsedHandler方法
private void OnElapsedHandler(object sender, System.Timers.ElapsedEventArgs e) { //String path = @"E:\Program\JobRun.txt"; // Check the local time ESTBranches = ConfigurationManager.AppSettings["EST"].ToString().Split(','); CSTBranches = ConfigurationManager.AppSettings["CST"].ToString().Split(','); MSTBranches = ConfigurationManager.AppSettings["MST"].ToString().Split(','); PSTBranches = ConfigurationManager.AppSettings["PST"].ToString().Split(','); DateTime currentDateTimeUTC = DateTime.UtcNow; int hour = Int32.Parse(currentDateTimeUTC.ToString("HH")); List<Model_Parts> lstParts = new List<Model_Parts>(); lstParts = mwQ.GetPartsQueue(); // Get list of unprocessed parts in MW from MB Auth auth = new Auth(); double elapsedMillisecs = ((TimeSpan)(DateTime.Now - auth.GenerateTime)).TotalMilliseconds; if (elapsedMillisecs > 3600000 || auth.AuthToken.Trim().Length == 0) { sfsOps.GetSFSAccessToken(); } sfsOps.BuildPartsJSON("Create", lstParts); }
排查与解决思路
- 排除内存缓存问题:
lstParts是方法内的局部变量,每次定时器触发都会重新创建并赋值,不存在上一次数据残留的情况,问题与内存清理无关。 - 检查标记更新逻辑:代码中仅调用了
sfsOps.BuildPartsJSON发送数据,但未看到接口返回成功后更新数据库标记的代码。如果缺失这一步,数据库中记录始终是未处理状态,mwQ.GetPartsQueue()会重复读取同批数据。 - 验证
GetPartsQueue()查询逻辑:- 确认该方法的SQL查询是否正确筛选未标记记录(例如
WHERE IsProcessed = 0)。 - 如果
mwQ是全局实例,检查其内部是否存在缓存机制(如将查询结果存在全局变量中未重新查询),需确保每次调用都重新读取数据库。
- 确认该方法的SQL查询是否正确筛选未标记记录(例如
- 处理定时器并发问题:
System.Timers.Timer默认多线程触发,若前一次处理未完成就触发下一次,可能导致重复读取。可修改定时器逻辑避免并发:private void OnElapsedHandler(object sender, System.Timers.ElapsedEventArgs e) { var timer = (System.Timers.Timer)sender; timer.Enabled = false; // 先禁用定时器,避免并发 try { // 原有业务逻辑 // 确认接口调用成功后,执行数据库标记更新 // mwQ.UpdateProcessedStatus(lstParts); // 需补充此方法实现 } finally { timer.Enabled = true; // 处理完成后重新启用定时器 } }
内容的提问来源于stack exchange,提问作者Avinash Shankar
相关产品推荐
相关产品推荐

