Windows服务中的计时器需要重新启动

本文关键字:重新启动 计时器 服务 Windows | 更新日期: 2023-09-27 18:06:38

我创建了一个带有计时器的windows服务,其中我需要设置每个Elapsed timer事件之后的间隔。例如,我想让它每小时整点开机。

在Program.cs:

namespace LabelLoaderService
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        /// 
        static void Main()
        {
#if (!DEBUG)
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[] 
            { 
                new LabelLoader() 
            };
            ServiceBase.Run(ServicesToRun);
#else
            LabelLoader ll = new LabelLoader();
            ll.Start();
#endif
        }
    }
}
在LabelLoader.cs:

namespace LabelLoaderService
{
    public partial class LabelLoader : ServiceBase
    { 
       System.Timers.Timer timer = new System.Timers.Timer();
    public LabelLoader()
    {
        InitializeComponent();
        timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
    }
    protected override void OnStart(string[] args)
    {
        SetTimer();
    }

    public void Start()
    {
        // Debug Startup            
        SetTimer();
    }

    public void SetTimer()
    {
        DateTime nextRunTime = GetNextRunTime();
        var ts = nextRunTime - DateTime.Now;
        timer.Interval = ts.TotalMilliseconds;
        timer.AutoReset = true;  // tried both true & false
        timer.Enabled = true;
        GC.KeepAlive(timer);  // test - no effect with/without this line
    }
    void timer_Elapsed(object source, ElapsedEventArgs e)
    {
        timer.Enabled = false;
        // do some work here
        SetTimer();
    }

如果我将这个安装到我的本地机器上,它会正确地确定下一个运行时并执行。但是在那之后它就不运行了。如果我重新启动服务,它会在下一个计划时间运行,然后又什么都不运行。是否有问题调用SetTimer()在我的处理结束时重置间隔和设置timer.Start()?

Windows服务中的计时器需要重新启动

使用System.Threading.Timer代替-根据我的经验,它更适合于类似服务器的使用…

编辑-根据注释一些代码/提示:

下面是一种非常基本的避免重新进入的方法(在这种特殊情况下应该可以工作)-更好的是lock/Mutex或类似的
使nextRunTime成为实例字段
创建/开始你的时间,例如

// first the TimerCallback, second the parameter (see AnyParam), then the time to start the first run, then the interval for the rest of the runs
timer = new System.Threading.Timer(new TimerCallback(this.MyTimerHandler), null, 60000, 30000);


创建类似于

的定时器处理程序
void MyTimerHandler (object AnyParam)
{
if ( nextRunTime > DateTime.Now) 
     return;
nextRunTime = DateTime.MaxValue; 
// Do your stuff here
// when finished do 
nextRunTime = GetNextRunTime();
}