【发布时间】:2016-02-17 17:17:43
【问题描述】:
我需要创建一个 Windows 服务(Windows 任务计划程序和 Quartz.net 等第三方库/实用程序对我来说不是选项),它每小时运行一次操作,每小时运行一次,从 12 小时开始8:00 AM。
我使用 System.Threading.Timer 编写的代码有时可以正常执行,但有时回调会提前几毫秒执行。如果我需要从目录中添加/删除文件,我觉得这将是一个问题。这是我第一次真正涉足 Windows 服务和计时器,因此我们将不胜感激。
这是我的代码:
private Timer timer;
private DateTime startTime; // Equals 8:00 AM
private DateTime endTime;
private Int32 interval; // Equals 1 hour
private Int32 duration; // Equals 12 hours
private DateTime nextRunTime;
private DateTime lastRunTime;
public ScheduleService()
{
InitializeComponent();
InitGlobalsFromConfigFile(); // This assigns values to the globals above.
}
protected override void OnStart(string[] args)
{
this.WriteToFile("Started {0}.");
this.StartService();
}
protected override void OnStop()
{
this.WriteToFile("Stopped {0}.");
timer.Dispose();
}
private void ScheduleService()
{
DateTime now = DateTime.Now;
DateTime runTime = new DateTime(now.Year, now.Month, now.Day, now.Hour, 0, 0, 0);
endTime = startTime.AddHours(duration);
if (now < startTime)
{
nextRunTime = startTime;
}
else if (now >= startTime && now < endTime)
{
nextRunTime = runTime.AddHours(interval);
}
else
{
nextRunTime = startTime.AddDays(1);
}
this.WriteToFile(string.Format("Now: {0}", DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss.ff tt")));
this.WriteToFile(string.Format("runTime: {0}", runTime.ToString("MM/dd/yyyy hh:mm:ss.ff tt")));
this.WriteToFile("Interval: " + interval.ToString() + " hour(s)");
this.WriteToFile("Duration: " + duration.ToString() + " hour(s)");
this.WriteToFile("Start Time: " + startTime.ToString());
this.WriteToFile("End Time: " + endTime.ToString());
this.WriteToFile(string.Format("Last Run Time: {0}", lastRunTime.ToString("MM/dd/yyyy hh:mm:ss.ff tt")));
this.WriteToFile(string.Format("Next Run Time: {0}", nextRunTime.ToString("MM/dd/yyyy hh:mm:ss.ff tt")));
try
{
timer = new Timer(new TimerCallback(ScheduleServiceCallback));
TimeSpan timeSpan = nextRunTime.Subtract(DateTime.Now);
int dueTime = Convert.ToInt32(timeSpan.TotalMilliseconds);
this.WriteToFile("dueTime: " + dueTime.ToString());
this.WriteToFile("");
timer.Change(dueTime, Timeout.Infinite);
}
catch (Exception ex)
{
this.WriteToFile("Error on: {0} " + ex.Message + ex.StackTrace);
using (System.ServiceProcess.ServiceController serviceController = new System.ServiceProcess.ServiceController("ScheduleService"))
{
serviceController.Stop();
}
}
}
private void ScheduleServiceCallback(object e)
{
this.WriteToFile("Log: {0}.");
lastRunTime = nextRunTime;
this.ScheduleService();
}
这是日志中的一个示例:
Started 02/17/2016 09:22:33.59 AM.
[Log entry #1]
Now: 02/17/2016 09:22:33.59 AM
runTime: 02/17/2016 09:00:00.00 AM
Interval: 1 hour(s)
Duration: 12 hour(s)
Start Time: 2/17/2016 7:00:00 AM
End Time: 2/17/2016 7:00:00 PM
Last Run Time: 01/01/0001 12:00:00.00 AM
Next Run Time: 02/17/2016 10:00:00.00 AM
Updated Now: 02/17/2016 09:22:33.59 AM
dueTime: 2246403
[Log entry #2]
Log: 02/17/2016 09:59:59.87 AM.
Now: 02/17/2016 09:59:59.87 AM
runTime: 02/17/2016 09:00:00.00 AM
Interval: 1 hour(s)
Duration: 12 hour(s)
Start Time: 2/17/2016 7:00:00 AM
End Time: 2/17/2016 7:00:00 PM
Last Run Time: 02/17/2016 10:00:00.00 AM
Next Run Time: 02/17/2016 10:00:00.00 AM
Updated Now: 02/17/2016 09:59:59.88 AM
dueTime: 118
[Log entry #3]
Log: 02/17/2016 10:00:00.00 AM.
Now: 02/17/2016 10:00:00.00 AM
runTime: 02/17/2016 10:00:00.00 AM
Interval: 1 hour(s)
Duration: 12 hour(s)
Start Time: 2/17/2016 7:00:00 AM
End Time: 2/17/2016 7:00:00 PM
Last Run Time: 02/17/2016 10:00:00.00 AM
Next Run Time: 02/17/2016 11:00:00.00 AM
Updated Now: 02/17/2016 10:00:00.00 AM
dueTime: 3599994
请注意,在日志条目 #2 中,nextRunTime 和 lastRunTime 是相同的值,而 Now 是上午 09:59:59.87 而不是上午 10:00:00.00。然后在日志条目 #3 中,似乎回调在不到一秒后再次运行。如何确保回调不会因为 nextRunTime 未更新而连续运行两次?
谢谢。
【问题讨论】:
标签: c# timer windows-services .net-4.5.2