在Windows服务内的计划中运行方法
本文关键字:运行 方法 计划 Windows 服务 | 更新日期: 2023-09-27 18:21:09
我有一个Windows服务,我需要在特定的Schedules中运行一个方法。到目前为止,我实现了一个表示时间表的类。
public class SchaduleTime
{
public int Hour { get; set; }
public int Minute { get; set; }
public DateTime Next
{
get
{
var now = DateTime.Now;
var dt = now.Date;
// the time has passed to execute today?
if (Hour * 60 + Minute < now.Hour * 60 + now.Minute)
{
dt = dt.AddDays(1);
}
return new DateTime(dt.Year, dt.Month, dt.Day, Hour, Minute, 0);
}
}
}
我创建了一个包含以下字段的主类:
System.Timers.Timer timer;
private SchaduleTime[] schadules;
并在计时器字段的Elapsed事件中运行类似的操作:
private void TimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
{
// do my work.
// programing next:
var nowTicks = DateTime.Now.Ticks;
// get the next schadule.
var next = schadules
.Select(s => new
{
Schadule = s,
IntervalNeeded = s.Next.Ticks - nowTicks
})
.OrderBy(o => o.IntervalNeeded)
.First();
timer.Enabled = false;
timer.Stop();
timer.Interval = (int) new TimeSpan(next.IntervalNeeded).TotalMilliseconds;
timer.Enabled = true;
timer.Start();
}
对我来说,这似乎是一个拙劣的策略或意大利面条代码,我的意思是看起来很丑陋。
有没有一种方法可以使用一个专门的类来实现这一点,该类可以处理调度或类似于.net中的Windows任务调度程序,或者我的方法很好,我吓坏了?
让我们考虑一下假设的情况,您在14:00有10个时间表。假设你的计时器在13:59:59停止,结果是:
- 10个时间表声称他们还有1秒
- 已运行的处理程序先拾取,然后每隔1秒重新启动
- 它在14:00再次停止,此时所有时间表都已返回第二天的
Next
因此,你已经完成了10份工作中的1份。看起来不太好。
当然,你们可以选择列表,或者限制在给定的时间内只能设置一个作业。但话说回来,你还需要做出哪些其他假设?时间表数组可以为空吗?当有100万个时间表时,它能工作吗?你有这个代码的测试吗?等等。
相反,您可以使用专门的库来执行,也就是-Quartz。这是一个简单的作业调度程序,它肯定可以做你想在这里实现的事情:
ISchedulerFactory factory= new StdSchedulerFactory();
IScheduler scheduler = factory.GetScheduler();
scheduler.Start();
// You'll have to implement class performing actual work to be done - ServiceJob
JobDetail jobDetail = new JobDetail("ServiceJob", null, typeof(ServiceJob));
Trigger trigger = TriggerUtils.MakeDailyTrigger();
// Start time could be anytime today
trigger.StartTimeUtc = DateTime.UtcNow;
trigger.Name = "ServiceTrigger";
scheduler.ScheduleJob(jobDetail, trigger);
Quartz负责所有计时器,在请求的时间运行指定的作业,等等。它很简单,有一套很好的教程,而且你不需要实现任何东西。
在我看来,您的方法很好。事实上,这是一种启发。我不会想出一个定时器并永久重新安排它。
我会做的是——这是严格可选的,就像我说的,你的方法很好——只是让计时器每分钟启动一次,然后检查是否有什么事情要做。如果时间分辨率较小,几秒甚至几毫秒,我不会这么做。但是,让你的计时器每分钟运行一次,只检查内存中的数组,在95%的情况下直接返回睡眠状态,并不是对资源的可怕浪费。此外,它还允许代码更加简单明了,更易于维护。