我有一个用C#(.NET 1.1)编写的服务,希望在每天午夜执行一些清理操作。由于必须将所有代码包含在服务中,因此最简单的方法是什么?使用Thread.Sleep()
和检查时间是否已转变?
我有一个用C#(.NET 1.1)编写的服务,希望在每天午夜执行一些清理操作。由于必须将所有代码包含在服务中,因此最简单的方法是什么?使用Thread.Sleep()
和检查时间是否已转变?
我不会使用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 job”语法。我在这方面取得了很多成功。
这是其使用的快速示例:
// 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控制面板中内置的定期任务吗?
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();
}
}
正如其他人所写的,定时器是您所描述情境中最好的选择。
根据您的确切要求,每分钟检查当前时间可能并不必要。如果您只需要在午夜之后的一小时内执行操作,而不是在午夜准确地执行操作,则可以采用马丁的方法仅检查日期是否发生变化。
如果您想在午夜时执行操作的原因是您希望计算机工作负载较低,请注意:同样的假设通常也会被其他人做出,并且突然间就有100个清理操作在0:00至0:01 a.m.之间启动。
在这种情况下,您应该考虑在不同的时间开始清理。我通常不是在整点进行这些操作,而是在半点(1.30 a.m.是我个人的首选)进行操作。
您也可以在此处尝试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
}
}