系统Windows 2008 R2安装程序Windows 2008用户控件系统管理员线程Windows VistaWindows 7设计 / 图形所有主题架构师高级C# 4.0中级开发Windows.NETC#
.NET 应用程序的任务调度程序库
一个简单的任务调度程序实用程序,您可以使用它来安排任务在任何时间或间隔运行
引言
这是一个简单的类,可用于安排任务在每天的特定时间运行或按一定间隔运行。 这可用于任何计划任务,例如清理文件或其他资源,将数据从任何外部数据提供程序同步到您的应用程序,定期优化数据库,在带宽使用较少的时段(可能在夜间)发送批量电子邮件或其他通知,例如短信等。
背景
我正在使用 .NET framework >=4.0 的 Task 类。 因此,请检查您的项目是否与此实用程序兼容。
Using the Code
有两种类型的任务调度可用
public enum ScheduleKind
{
// Scheduler which triggers at a specific time interval
IntervalBased = 0,
// Scheduler which runs at a specific time of everyday.
TimeBased = 1
}
主要的关注类是 Scheduler
类。 这个类继承自 System.Timers.Timer 类并提供任务调度功能。
// Used to schedule tasks to run on regular intervals or on specific time of everyday.
public class Scheduler : Timer, IDisposable
{
private Scheduler() { }
private TimeSpan _Time { get; set; }
private ScheduleKind _Kind { get; set; }
// Returns a new instance of timer and starts it
// param name="Time": Interval time to execute the timer
// param name="Trigger": Function to call in a new Thread when timer elapses, signal time is given as
// input parameter to the function
// param name="Kind": Specify scheduler type
// returns: A System.Timers.Timer Instance
public static Scheduler StartNew(TimeSpan Time, Action<datetime> Trigger,
ScheduleKind Kind = ScheduleKind.IntervalBased)
{
Scheduler timer = MakeTimer(Time, Kind);
timer.Elapsed += (s, e) => Task.Factory.StartNew(() => Trigger(e.SignalTime));
return timer;
}
// Returns a new instance of timer and starts it
// param name="Time": Interval time to execute the timer
// param name="Trigger": Function to call in a new Thread when timer elapses, signal time is given as
// input parameter to the function
// param name="Kind": Specify scheduler type
// param name="CallBackFn": Optional call back Action to execute after completing the Trigger function.
// Input parameter of this Action is the result of Trigger function
// returns: A System.Timers.Timer Instance
public static Scheduler StartNew<t>(TimeSpan Time, Func<datetime> Trigger,
ScheduleKind Kind = ScheduleKind.IntervalBased, Action<t> CallBackFn = null)
{
Scheduler timer = MakeTimer(Time, Kind);
timer.Elapsed += (s, e) =>
{
if (CallBackFn != null)
{
Task.Factory.StartNew(() => Trigger(e.SignalTime))
.ContinueWith(prevTask => CallBackFn(prevTask.Result));
}
else
{
Task.Factory.StartNew(() => Trigger(e.SignalTime));
}
};
return timer;
}
// Returns a new instance of timer and starts it
// param name="Time">Interval time to execute the timer
// param name="Trigger": Function to call in a new Thread when timer elapses, signal time is given as
// input parameter to the function
// param name="Kind": Specify scheduler type
// param name="CallBackFn": Optional call back function to execute after completing the Trigger function.
// Input parameter of this function is the result of Trigger function
// returns: A System.Timers.Timer Instance
public static Scheduler StartNew<t, v>(TimeSpan Time, Func<datetime> Trigger,
ScheduleKind Kind = ScheduleKind.IntervalBased, Func<t, v> CallBackFn = null)
{
Scheduler timer = MakeTimer(Time, Kind);
timer.Elapsed += (s, e) =>
{
if (CallBackFn != null)
{
Task.Factory.StartNew(() => Trigger(e.SignalTime))
.ContinueWith(prevTask => CallBackFn(prevTask.Result));
}
else
{
Task.Factory.StartNew(() => Trigger(e.SignalTime));
}
};
return timer;
}
// Resets and restarts the scheduler
public void Reset()
{
Stop();
switch (_Kind)
{
case ScheduleKind.IntervalBased:
Interval = _Time.TotalMilliseconds;
break;
case ScheduleKind.TimeBased:
Interval = GetTimeDiff();
break;
}
Enabled = true;
Start();
}
// Creates a timer
private static Scheduler MakeTimer(TimeSpan Time, ScheduleKind Kind = ScheduleKind.IntervalBased)
{
var timer = new Scheduler { _Time = Time, _Kind = Kind };
timer.Reset();
return timer;
}
// Returns TimeSpan difference of the next schedule time relative to current time
private double GetTimeDiff()
{
try
{
// Scheduled time of today
var nextRunOn =
DateTime.Today.AddHours(_Time.Hours).AddMinutes(_Time.Minutes).AddSeconds(_Time.Seconds);
if (nextRunOn < DateTime.Now)
{
nextRunOn = nextRunOn.AddMinutes(1);
}
if (nextRunOn < DateTime.Now) // If nextRunOn time is already past, set to next day
{
nextRunOn = nextRunOn.AddDays(1);
}
return (nextRunOn - DateTime.Now).TotalMilliseconds;
}
catch (Exception ex)
{
ex.WriteLog();
return 24 * 60 * 60 * 1000;
}
}
// Stop and dispose the timer
protected override void Dispose(bool disposing)
{
Stop();
base.Dispose(disposing);
}
}
使用 Scheduler
类非常简单。
// A function that executes every 5 minutes
FiveMinScheduler = Scheduler.StartNew(TimeSpan.FromMinutes(5),
_ => FiveMinScheduledFn()); // Runs on every 5 minutes
// A function that executes only once in a day at a specific time
NightScheduler = Scheduler.StartNew(TimeSpan.FromHours(2), NightScheduledFn, ScheduleKind.TimeBased); // Runs on 2AM everyday
// Using parameters in a schedule function
ParamerizedScheduler = Scheduler.StartNew(TimeSpan.FromDays(7),
_ => ParamerizedScheduledFn(i, 6)); // Runs once in a week
// Using result of scheduled function in another callback function
CallbackScheduler = Scheduler.StartNew(TimeSpan.FromSeconds(30), _ => ParamerizedScheduledFn(i, 6),
ScheduleKind.IntervalBased, CallBackFunc); // Runs on every 15 seconds
以下是以上示例中使用的一些示例方法,这些方法被传递给 Scheduler.StartNew()
帮助程序方法。
internal void NightScheduledFn(DateTime initTime)
{
Helper.WriteLog("I run at 2AM everyday. Current time is: " + DateTime.Now);
}
internal string ParamerizedScheduledFn(int i, int j)
{
Helper.WriteLog(String.Format("Got parameters i={0}
and j={1}. Current time is: {2}", i, j, DateTime.Now));
return (i*j).ToString(CultureInfo.InvariantCulture);
}
internal void CallBackFunc(string result)
{
Helper.WriteLog(String.Format("Scheduled task finished on: {0}.
Result of scheduled task is: {1}", DateTime.Now, result));
}
要停止 Scheduler
,请调用 schedulerObject.Stop()
。
要重新启动 Scheduler
,请调用 schedulerObject.Reset()
。
关注点
您可以在附带的源代码中找到一个带有自安装程序选项的 Windows 服务。
同时,查看 使用模板模式的实现行为更改,这是 John Brett 建议的。