65.9K
CodeProject 正在变化。 阅读更多。
Home

用于 .NET 应用程序的任务调度程序库

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2014年6月11日

MIT

1分钟阅读

viewsIcon

21469

downloadIcon

385

这是“用于 .NET 应用程序的任务调度程序库”的替代方案

引言

这是一个简单的类,可用于安排每天在特定时间运行任务,或每隔一段时间运行任务。 这可用于任何计划任务,例如清理文件或任何其他资源、将数据从任何外部数据提供程序同步到您的应用程序、定期优化数据库、发送批量电子邮件或其他通知(例如在带宽使用较少的时间(可能在夜间)发送 SMS)等。

背景

我在解决方案中使用 .NET framework >=4.0 类 Task。 因此,请检查您的项目是否与此实用程序兼容。 这是一个尝试,旨在为“用于 .NET 应用程序的任务调度程序库”创建一个替代方案,并通过将 Scheduler 类拆分为两个类来获得更简洁的设计,正如 John Brett此评论中建议的那样。

Using the Code

在此设计中,有一个 abstract 泛型类 ServiceBase。 我更喜欢使用 abstract 类而不是 interface 来实现代码重用。

// Used to schedule tasks to run on regular intervals or on specific time of everyday.
public abstract class SchedulerBase<T> : Timer, IDisposable
{
    // Returns a new instance of timer and starts it
    // param name="Time": Interval time to execute the timer
    // param name="Trigger": Action to call in a new Thread when timer elapses
    protected SchedulerBase(TimeSpan Time, Action Trigger)
    {
        this.Time = Time;
        Reset();
        Elapsed += (s, e) => Task.Factory.StartNew(Trigger);
    }

    // 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
    // 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
    protected SchedulerBase(TimeSpan Time, Func<T> Trigger, Action<T> CallBackFn)
    {
        this.Time = Time;
        Reset();
        Elapsed += (s, e) => Task.Factory.StartNew(Trigger)
            .ContinueWith(prevTask => CallBackFn(prevTask.Result));
    }

    protected TimeSpan Time { get; set; }

    // Resets and restarts the scheduler
    public void Reset()
    {
        Stop();
        Interval = GetInterval();
        Enabled = true;
        Start();
    }

    // A template method to return TimeSpan difference of the next schedule time with respect to current time
    protected abstract double GetInterval();

    // Stop and dispose the timer
    protected override void Dispose(bool disposing)
    {
        Stop();
        base.Dispose(disposing);
    }
}

IntervalScheduler 是继承自 SchedulerBase 类的具体类之一。 此类提供基于间隔的调度行为。

// Scheduler which triggers at a specific time interval
public class IntervalScheduler<T> : SchedulerBase<T>
{
    public IntervalScheduler(TimeSpan Time, Action Trigger) : base(Time, Trigger) { }

    public IntervalScheduler(TimeSpan Time, Func<T> 
    Trigger, Action<T> CallBackFn) : base(Time, Trigger, CallBackFn) { }

    protected override double GetInterval()
    {
        return Time.TotalMilliseconds;
    }
}

TimeScheduler 是另一个继承自 SchedulerBase 的类,它提供在一天中的特定时间运行调度程序的行为。

// Scheduler which runs at a specific time everyday.
public class TimeScheduler<T> : SchedulerBase<T>
{
    public TimeScheduler(TimeSpan Time, Action Trigger) : base(Time, Trigger) { }

    public TimeScheduler(TimeSpan Time, Func<T> Trigger, 
    Action<T> CallBackFn) : base(Time, Trigger, CallBackFn) { }

    protected override double GetInterval()
    {
        // Scheduled time of today
        DateTime 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;
    }
}

您可以通过简单地调用特定的构造函数来创建调度程序。

// A function that executes every 5 minutes
SchedulerBase<dynamic> FiveMinScheduler = 
new IntervalScheduler<dynamic>(TimeSpan.FromMinutes(5), FiveMinScheduledFn);

// A function that executes only once in a day at a specific time
SchedulerBase<dynamic> NightScheduler = 
new TimeScheduler<dynamic>(TimeSpan.FromHours(2), NightScheduledFn);

// Using parameters in a schedule function
SchedulerBase<dynamic> ParamerizedScheduler = 
new IntervalScheduler<dynamic>(TimeSpan.FromDays(7), () => ParamerizedScheduledFn(i, 6));

// Using result of scheduled function in another callback function
SchedulerBase<string> CallbackScheduler = 
new IntervalScheduler<string>(TimeSpan.FromSeconds(30), 
    () => ParamerizedScheduledFn(i, 6), CallBackFunc);

上面使用的一些计划函数是

internal void NightScheduledFn()
{
    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 类拆分为两个类如何实现更简洁的设计。

请参阅使用工厂模式的替代实现。

© . All rights reserved.