You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WebApi中ApplicationStart方法内两个System.Timers.Timer无法正常工作

WebApi中System.Timers.Timer事件未触发问题解决

问题描述

在.NET WebApi项目中,因限制无法使用EXE程序,只能基于WebApi实现两个独立的System.Timers.Timer(已知WebApi中使用定时器并非最佳实践)。在Application_Start方法中声明并启动两个定时器后,仅FetchTimer的事件处理函数正常触发,HSMSentTimer的处理函数未执行。

预期行为

  • FetchTimer:API启动时立即启动,从客户端API获取数据并插入数据库
  • HSMSentTimer:API启动时并行启动,从数据库获取数据,按间隔发送至另一API并执行业务逻辑

现有代码

public class WebApiApplication : System.Web.HttpApplication
{
    public static LogBO _globalObjects = new LogBO(WebConfigurationManager.AppSettings["LogFileDrive"], WebConfigurationManager.AppSettings["LogFolderName"]);
    public Timer FetchTimer;
    public Timer HSMSentTimer;
    public static DAO_ dao = new DAO_();
    public static SqlConnection sqlConnection;
    protected void Application_Start()
    {
        FetchTimer = new Timer();
        FetchTimer.Elapsed += new ElapsedEventHandler(FetchTimerHandler);
        FetchTimer.Interval = 3000;
        FetchTimer.AutoReset = false;
        FetchTimer.Start();
        WriteLog.WriteInfoLog(_globalObjects, "..............", ".......................");
        HSMSentTimer = new Timer();
        HSMSentTimer.Elapsed += new ElapsedEventHandler(HSMSentTimerHandler);
        HSMSentTimer.Interval = 6000;
        // 此处错误:修改的是FetchTimer的AutoReset,而非HSMSentTimer
        FetchTimer.AutoReset = false;
        HSMSentTimer.Start();
    }

    public void FetchTimerHandler(object sender, ElapsedEventArgs eventArgs)
    {
        FetchTimer.Stop();
        WriteLog.WriteInfoLog(_globalObjects, "FetchTimerHandler()", "FetchTimerHandler started..... ");
    }

    public void HSMSentTimerHandler(object sender, ElapsedEventArgs eventArgs)
    {
        HSMSentTimer.Stop();
        WriteLog.WriteInfoLog(_globalObjects, "HSMSentTimerHandler()", "HSMSent timer started..... ");
    }
}

当前输出

.............. | .......................
FetchTimerHandler() | FetchTimerHandler started.....

问题原因及解决方法

1. 代码笔误

初始化HSMSentTimer时,错误地重复设置FetchTimer.AutoReset = false;,而非设置HSMSentTimer.AutoReset。虽该笔误本身不直接导致触发失败,但结合实例回收问题会加剧异常。

2. 定时器实例被垃圾回收

ASP.NET的HttpApplication实例并非长期驻留,运行时可能回收该实例,而你的定时器是实例字段,会随实例被回收销毁,导致HSMSentTimer无法触发事件。

解决:将定时器改为静态字段
修改定时器声明为静态:

public static Timer FetchTimer;
public static Timer HSMSentTimer;

3. 单次触发逻辑调整(可选)

当前代码中AutoReset = false且处理函数调用Stop(),定时器仅触发一次。若需重复执行,可二选一:

  • 将AutoReset设为true,无需手动启停
  • 在处理函数完成业务逻辑后,重新调用Start()方法

调整后的Application_Start示例(静态定时器+修正笔误):

protected void Application_Start()
{
    FetchTimer = new Timer();
    FetchTimer.Elapsed += FetchTimerHandler;
    FetchTimer.Interval = 3000;
    FetchTimer.AutoReset = false; // 需重复执行则改为true
    FetchTimer.Start();
    WriteLog.WriteInfoLog(_globalObjects, "..............", ".......................");
    
    HSMSentTimer = new Timer();
    HSMSentTimer.Elapsed += HSMSentTimerHandler;
    HSMSentTimer.Interval = 6000;
    HSMSentTimer.AutoReset = false; // 修正笔误,设置自身的AutoReset
    HSMSentTimer.Start();
}

额外注意事项

  • WebApi中使用定时器需注意应用池回收问题,可配置应用池避免自动回收,或添加回收后重启定时器的逻辑
  • 定时器事件处理函数在后台线程执行,需注意线程安全,尤其是数据库操作等共享资源访问

内容的提问来源于stack exchange,提问作者au7 au7

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 01:01:24