我有一个Windows服务,我需要在特定的日程表中运行一个方法。到目前为止,我实现了一个代表时间表的类。
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();
}
好的,你现在可以告诉我一切准备就绪,我不需要帮助并给我一个投票,但请不要,首先让我问这个问题:
对我而言,这似乎是一种kludge策略或意大利面条代码,我的意思是看起来很难看。
问题:
有没有办法使用一个专门的类来处理调度或类似Windows内部的任务调度程序。或者我的方法很好,我吓坏了吗?
答案 0 :(得分:2)
让我们考虑一下假设的情况,即14:00有10个时间表。假设您的计时器在13:59:59停止,会发生什么:
Next
时结果,你已经完成了10个工作中的1个。看起来不太好。
当然,您可以列出或限制在给定时间内只能设置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负责所有计时器,在请求的时间运行指定的作业等等。它很简单,有很好的tutorials组合 - 你不需要实现任何东西。
答案 1 :(得分:1)
在我看来,你的方法很好。实际上,它有点灵感。我不会想出一个计时器并永久重新安排它。
我会做什么 - 这是严格可选的,就像我说的,你的方法很好 - 只是让计时器每分钟点火并检查是否有事情要做。使用较小的时间分辨率,几秒甚至几毫秒,我不会这样做。但让你的计时器每分钟运行一次,只需检查一个内存阵列,并在95%的情况下直接回到睡眠状态,这几乎不会浪费资源。此外,它还允许代码更直接,更易于维护。