Windows服务在指定时间运行函数

我想启动Windows服务,以便在特定时间每天运行一个function。

我应该考虑采用什么方法来实现这个? 定时器还是使用线程?

(1)首次启动时,将_timer.Interval设置为服务启动和调度时间之间的毫秒数。 此样本设置的时间表为上午7:00,因为_scheduleTime = DateTime.Today.AddDays(1).AddHours(7);

(2)在Timer_Elapsed上,如果当前间隔不是24小时,则将_timer.Interval重置为24小时(以毫秒为单位)。

System.Timers.Timer _timer; DateTime _scheduleTime; public WinService() { InitializeComponent(); _timer = new System.Timers.Timer(); _scheduleTime = DateTime.Today.AddDays(1).AddHours(7); // Schedule to run once a day at 7:00 am } protected override void OnStart(string[] args) { // For first time, set amount of seconds between current time and schedule time _timer.Enabled = true; _timer.Interval = _scheduleTime.Subtract(DateTime.Now).TotalSeconds * 1000; _timer.Elapsed += new System.Timers.ElapsedEventHandler(Timer_Elapsed); } protected void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { // 1. Process Schedule Task // ---------------------------------- // Add code to Process your task here // ---------------------------------- // 2. If tick for the first time, reset next run to every 24 hours if (_timer.Interval != 24 * 60 * 60 * 1000) { _timer.Interval = 24 * 60 * 60 * 1000; } } 

编辑:

有时人们希望将服务安排在第0天开始,而不是明天开始,因此他们更改DateTime.Today.AddDays(0) 。如果他们这样做并在过去设置时间,则会导致错误,将Interval设置为负数。

 //Test if its a time in the past and protect setting _timer.Interval with a negative number which causes an error. double tillNextInterval = _scheduleTime.Subtract(DateTime.Now).TotalSeconds * 1000; if (tillNextInterval < 0) tillNextInterval += new TimeSpan(24, 0, 0).TotalSeconds * 1000; _timer.Interval = tillNextInterval; 

很好的答案(我使用了你的代码),但这一行有一个问题:

 _timer.Interval = _scheduleTime.Subtract(DateTime.Now).TotalSeconds * 1000; 

如果DateTime.now晚于scheduleTime,您将变为负数,这将在分配给timer.Interval时生成exception。

我用了:

 if (DateTime.now > scheduleTime) scheduleTime = scheduleTime.AddHours(24); 

然后进行减法。

使用Windows内置的任务计划程序( http://windows.microsoft.com/en-us/windows7/schedule-a-task )或Quartz.net。

除非……你有一项服务正在进行许多其他处理,并且需要一直运行,在这种情况下,Timer可能是合适的。

您确定,您需要一项每天只运行一次的服务吗?

也许Windows任务计划将是更好的解决方案?

 private static double scheduledHour = 10; private static DateTime scheduledTime; public WinService() { scheduledTime = DateTime.Today.AddHours(scheduledHour);//setting 10 am of today as scheduled time- service start date } private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { DateTime now = DateTime.Now; if (scheduledTime < DateTime.Now) { TimeSpan span = now - DateTime.Now; scheduledTime = scheduledTime.AddMilliseconds(span.Milliseconds).AddDays(1);// this will set scheduled time to 10 am of next day while correcting the milliseconds //do the scheduled task here } } 

你可以用线程和事件来做; 不需要计时器。

 using System; using System.ServiceProcess; using System.Threading; partial class Service : ServiceBase { Thread Thread; readonly AutoResetEvent StopEvent; public Service() { InitializeComponent(); StopEvent = new AutoResetEvent(initialState: false); } protected override void Dispose(bool disposing) { if (disposing) { StopEvent.Dispose(); components?.Dispose(); } base.Dispose(disposing); } protected override void OnStart(string[] args) { Thread = new Thread(ThreadStart); Thread.Start(TimeSpan.Parse(args[0])); } protected override void OnStop() { if (!StopEvent.Set()) Environment.FailFast("failed setting stop event"); Thread.Join(); } void ThreadStart(object parameter) { while (!StopEvent.WaitOne(Timeout(timeOfDay: (TimeSpan)parameter))) { // do work here... } } static TimeSpan Timeout(TimeSpan timeOfDay) { var timeout = timeOfDay - DateTime.Now.TimeOfDay; if (timeout < TimeSpan.Zero) timeout += TimeSpan.FromDays(1); return timeout; } }