我有一个用C#(.NET 1.1)编写的服务,希望它在每晚的午夜执行一些清理操作。我必须将所有代码包含在服务中,那么最简单的方法是什么?使用Thread.Sleep()
时间检查时间吗?
我有一个用C#(.NET 1.1)编写的服务,希望它在每晚的午夜执行一些清理操作。我必须将所有代码包含在服务中,那么最简单的方法是什么?使用Thread.Sleep()
时间检查时间吗?
Answers:
我不会使用Thread.Sleep()。使用预定任务(如其他人所述),或在服务内部设置计时器,该计时器会定期触发(例如每10分钟触发一次),并检查日期是否自上次运行以来已更改:
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服务中使用它。它允许您根据配置的时间表运行作业,甚至还支持简单的“ 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 / Hour检查中。
那里有钩子可以进行测试,等等。但这就是您的计时器已使所有工作正常运行的样子。
我建议您使用计时器,但将其设置为每45秒而不是每分钟检查一次。否则,您可能会遇到繁重的工作,错过了对特定分钟的检查,因为在计时器触发与代码运行并检查当前时间之间,您可能错过了目标分钟。
您也可以在这里尝试TaskSchedulerLibrary http://visualstudiogallery.msdn.microsoft.com/a4a4f042-ffd3-42f2-a689-290ec13011f8
实现抽象类AbstractScheduledTask
并调用ScheduleUtilityFactory.AddScheduleTaskToBatch
静态方法
对于发现上述解决方案不起作用的用户,这是因为您可能this
在类的内部,这暗示了一种扩展方法,正如错误消息所述,该方法仅对非通用静态类有意义。您的课程不是静态的。作为扩展方法,这似乎没有什么意义,因为它作用在所讨论的实例上,因此请删除this
。
试试这个:
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
}
}