ASP.NET定时任务异常:单任务失控、偶发停止运行求助
ASP.NET定时任务异常问题排查与解决
我用Visual Studio 2022社区版开发了一套ASP.NET系统,近期某功能模块出现异常:三个定时任务里,一个任务失控,另外两个运行正常。这个任务曾出现执行系统逻辑但未给用户发消息的情况,日志里也没相关提示。每次任务停了之后重启程序能恢复,但过段时间又会停。之前重新生成过Bin文件,怀疑是不是这个导致的问题?
相关代码
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); GlobalConfiguration.Configure(WebApiConfig.Register); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); try { LogFile.WriteError(DateTime.Now + "Start"); var checkWorkInterval = double.Parse((CachedConfigContext.Current.CheckWorkConfig.Interval * 1000).ToString()); Timer checkWorTime = new Timer(checkWorkInterval); checkWorTime.Elapsed += new System.Timers.ElapsedEventHandler(CheckWorkEvent); checkWorTime.AutoReset = true; checkWorTime.Enabled = Convert.ToBoolean(CachedConfigContext.Current.CheckWorkConfig.MasterSwitch); } catch (Exception ex) { LogFile.WriteError(DateTime.Now + "error" + ex.ToString()); } } protected void Application_End() { LogFile.WriteError("Start 0230"); System.Threading.Thread.Sleep(5000); string strUrl = "http://" + Application["WebApiUri_Authority"].ToString() + "/api/Msg/Post"; string strRec = HttpClientHelper.PostData("", strUrl, "", "", HttpClientHelper.PostContentType.JSON); } private void CheckWorkEvent(object sender, ElapsedEventArgs e) { var time = (Timer)sender; DateTime nowDate = DateTime.Now; try { DateTime startDate = CachedConfigContext.Current.CheckWorkConfig.StartTime;//22:00 DateTime endDate = CachedConfigContext.Current.CheckWorkConfig.EndTime;//23:00 if (startDate <= nowDate && nowDate <= endDate) { time.Stop(); LogFile.WriteError(DateTime.Now + "Start"); var count = checkworkBll.CheckWorkCreate(); time.Start(); } } catch (Exception ex) { LogFile.WriteError(DateTime.Now + "error" + ex.ToString()); time.Start(); } }
问题原因分析
- Timer被垃圾回收:Application_Start中创建的Timer是局部变量,没有全局引用,GC运行时可能将其回收,导致定时任务停止。这是此类问题最常见的根源。
- 时间判断逻辑错误:配置的StartTime/EndTime仅包含时分(如22:00),但nowDate是完整的DateTime(含年月日),直接比较会导致只有当前日期与配置的日期完全相同时才会执行逻辑,其余时间任务看似“停止”。
- 日志与异常覆盖不足:CheckWorkEvent的日志仅记录进入执行的情况,未覆盖消息发送环节,无法排查“执行逻辑但未发消息”的问题;若Timer的Elapsed事件触发时出现未捕获异常,可能导致任务终止。
- Bin文件重新生成的影响:重新生成Bin本身不会直接引发问题,但如果生成时替换了依赖库版本、误改配置文件,可能间接导致异常,但概率较低。
解决方案
- 全局持有Timer引用:将Timer定义为全局静态变量,避免被GC回收:
private static Timer _checkWorkTimer; protected void Application_Start() { // 原有初始化代码... try { LogFile.WriteError(DateTime.Now + "Start"); var checkWorkInterval = double.Parse((CachedConfigContext.Current.CheckWorkConfig.Interval * 1000).ToString()); _checkWorkTimer = new Timer(checkWorkInterval); _checkWorkTimer.Elapsed += CheckWorkEvent; _checkWorkTimer.AutoReset = true; _checkWorkTimer.Enabled = Convert.ToBoolean(CachedConfigContext.Current.CheckWorkConfig.MasterSwitch); } catch (Exception ex) { LogFile.WriteError(DateTime.Now + "error" + ex.ToString()); } } - 修复时间判断逻辑:仅比较时间部分,忽略年月日:
private void CheckWorkEvent(object sender, ElapsedEventArgs e) { var time = (Timer)sender; var nowTime = DateTime.Now.TimeOfDay; try { var startTime = CachedConfigContext.Current.CheckWorkConfig.StartTime.TimeOfDay; var endTime = CachedConfigContext.Current.CheckWorkConfig.EndTime.TimeOfDay; if (nowTime >= startTime && nowTime <= endTime) { time.Stop(); LogFile.WriteError(DateTime.Now + "Start"); var count = checkworkBll.CheckWorkCreate(); // 新增日志:记录CheckWorkCreate的结果,确认逻辑是否执行成功 LogFile.WriteError(DateTime.Now + $"CheckWorkCreate执行完成,返回值:{count}"); time.Start(); } } catch (Exception ex) { LogFile.WriteError(DateTime.Now + "error" + ex.ToString()); time.Start(); } } - 完善日志与异常处理:
- 在消息发送环节添加日志,确认是否调用发送接口、返回结果是什么。
- 新增全局异常捕获(Application_Error),避免未处理异常导致应用池崩溃:
protected void Application_Error(object sender, EventArgs e) { Exception ex = Server.GetLastError(); LogFile.WriteError(DateTime.Now + "全局异常:" + ex.ToString()); Server.ClearError(); }
- 验证Bin文件与配置:对比重新生成前后的Bin文件,确认依赖库版本一致;检查配置文件中StartTime/EndTime的格式是否正确,确保未被误修改。
内容的提问来源于stack exchange,提问作者Mirza
相关产品推荐
相关产品推荐

