我如何安排一个C#Windows服务每天执行一项任务?

我有用C#(.NET 1.1)编写的服务,并希望它在每天晚上的午夜执行一些清理操作。 我必须保持服务中包含的所有代码,那么完成这个最简单的方法是什么? 使用Thread.Sleep()并检查滚动的时间?

我不会使用Thread.Sleep()。 或者使用计划任务(如其他人所提到的),或者在服务中设置一个定时器(例如每10分钟一次),检查自上次运行以来date是否发生了变化:

 private Timer _timer; private DateTime _lastRun = DateTime.Now.AddDays(-1); protected override void OnStart(string[] args) { _timer = new Timer(10 * 60 * 1000); // every 10 minutes _timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed); _timer.Start(); //... } private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { // ignore the time, just compare the date if (_lastRun.Date < DateTime.Now.Date) { // stop the timer while we are running the cleanup task _timer.Stop(); // // do cleanup stuff // _lastRun = DateTime.Now; _timer.Start(); } } 

看看Quartz.NET 。 您可以在Windows服务中使用它。 它允许您根据configuration的计划运行作业,甚至支持简单的“cron作业”语法。 我已经取得了很多成功。

以下是其用法的一个简单示例:

 // Instantiate the Quartz.NET scheduler var schedulerFactory = new StdSchedulerFactory(); var scheduler = schedulerFactory.GetScheduler(); // Instantiate the JobDetail object passing in the type of your // custom job class. Your class merely needs to implement a simple // interface with a single method called "Execute". var job = new JobDetail("job1", "group1", typeof(MyJobClass)); // Instantiate a trigger using the basic cron syntax. // This tells it to run at 1AM every Monday - Friday. var trigger = new CronTrigger( "trigger1", "group1", "job1", "group1", "0 0 1 ? * MON-FRI"); // Add the job to the scheduler scheduler.AddJob(job, true); scheduler.ScheduleJob(trigger); 

每日任务? 听起来应该只是一个计划任务(控制面板) – 这里不需要服务。

它是否必须是实际的服务? 你可以使用Windows控制面板中的内置计划任务吗?

我完成这个任务的方式是使用计时器。

运行服务器计时器,每隔60秒检查一次小时/分钟。

如果这是正确的小时/分钟,然后运行你的过程。

我实际上已经把这个抽象成一个叫做OnceAdayRunner的基类。

让我清理一下代码,然后在这里发布。

  private void OnceADayRunnerTimer_Elapsed(object sender, ElapsedEventArgs e) { using (NDC.Push(GetType().Name)) { try { log.DebugFormat("Checking if it's time to process at: {0}", e.SignalTime); log.DebugFormat("IsTestMode: {0}", IsTestMode); if ((e.SignalTime.Minute == MinuteToCheck && e.SignalTime.Hour == HourToCheck) || IsTestMode) { log.InfoFormat("Processing at: Hour = {0} - Minute = {1}", e.SignalTime.Hour, e.SignalTime.Minute); OnceADayTimer.Enabled = false; OnceADayMethod(); OnceADayTimer.Enabled = true; IsTestMode = false; } else { log.DebugFormat("Not correct time at: Hour = {0} - Minute = {1}", e.SignalTime.Hour, e.SignalTime.Minute); } } catch (Exception ex) { OnceADayTimer.Enabled = true; log.Error(ex.ToString()); } OnceADayTimer.Start(); } } 

该方法的牛肉是在e.SignalTime.Minute /小时检查。

在那里有钩子进行testing等,但这是你的计时器可能看起来像使所有的工作。

正如其他人已经写过的,在你描述的场景中,计时器是最好的select。

根据您的确切要求,可能不需要每分钟检查一次当前时间。 如果你不需要在午夜之后,而是在午夜之后的一个小时之内执行这个动作,你可以采取马丁的方法 ,只检查date是否改变。

如果您希望在午夜执行操作的原因是您希望计算机上的工作负载较低,那么请注意:其他人经常会做出相同的假设,并且突然间您有100次清理操作将在0:00和0之间启动:上午01点

在这种情况下,你应该考虑在不同的时间开始清理。 我通常不是在时钟时间做这些事情,而是半小时(上午1点30分是我个人的偏好)

我build议你使用一个计时器,但设置为每45秒检查一次,而不是一分钟。 否则,您可能会遇到负载过重的情况,因为在计时器触发和代码运行时间之间错过了特定分钟的检查,并检查当前时间,您可能错过了目标分钟。

这是我的一段代码:

  protected override void OnStart(string[] args) { timer = new Timer(); //Initialize the globally declared timer //SETTING THE INTERVAL FROM CONFIG FILE (10 SECONDS) timer.Interval = Convert.ToInt32(ConfigurationManager.AppSettings["TimerInterval"]); timer.Enabled = true; timer.Elapsed += timer_Elapsed; } 

在你的事件中,你可以这样做:

 private void timer_Elapsed(object sender, ElapsedEventArgs e) { timer.Enabled = false; string ScheduleTime = GlobalVariables.ScheduledTime;//GETTING SCHEDULED TIME FROM CONFIG IN (HH:mm) FORMAT string CurrentHourMin = DateTime.Now.ToString("HH:mm");//GETTING CURRENT TIME IN HH:mm format if (ScheduleTime == CurrentHourMin) { // YOUR CODE } System.Threading.Thread.Sleep(60000); //Putting thread to sleep for 60 seconds to skip the current minute to avoid re-execution of code timer.Enabled = true; } 

您也可以尝试这里的TaskSchedulerLibrary http://visualstudiogallery.msdn.microsoft.com/a4a4f042-ffd3-42f2-a689-290ec13011f8

实现抽象类AbstractScheduledTask并调用ScheduleUtilityFactory.AddScheduleTaskToBatch静态方法

尝试这个:

 public partial class Service : ServiceBase { private Timer timer; public Service() { InitializeComponent(); } protected override void OnStart(string[] args) { SetTimer(); } private void SetTimer() { if (timer == null) { timer = new Timer(); timer.AutoReset = true; timer.Interval = 60000 * Convert.ToDouble(ConfigurationManager.AppSettings["IntervalMinutes"]); timer.Elapsed += new ElapsedEventHandler(timer_Elapsed); timer.Start(); } } private void timer_Elapsed(object source, System.Timers.ElapsedEventArgs e) { //Do some thing logic here } protected override void OnStop() { // disposed all service objects } }