开发者

Timer in Windows service requires restart

I created a windows service with a timer in it, where I need to set set the interval after each Elapsed timer event. For example, I'd like it to fire on the hour every hour.

In 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

        }
    }
}

In 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();
    }

If I installutil this onto my local machine, it correctly determines the next run time and executes. But it doesnt run anytime after that. If I restart the service it runs the next scheduled time and then nothing again. Is there an issue calling SetTimer() at the end of my processing to reset the Interval and set timer.Start()?


use System.Threading.Timer instead - in my experience it is more suited for server-like use...

EDIT - as per comment some code/hints:

the following is a very basic way to avoid reentry (should work ok in this specific case) - better would be some lock/Mutex or similar
make nextRunTime an instance field
create/start your time with for example

// 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);


create your timer handler similar to

void MyTimerHandler (object AnyParam)
{
if ( nextRunTime > DateTime.Now) 
     return;

nextRunTime = DateTime.MaxValue; 
// Do your stuff here
// when finished do 
nextRunTime = GetNextRunTime();
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜