Windows服务 - 它可以运行以不同间隔安排的两个单独任务

时间:2015-08-13 12:50:46

标签: c# .net service windows-services

我编写了一个Windows服务,在特定时间在WEEK中触发电子邮件ONCE。该服务运行完美。代码如下所示:

  protected override void OnStart(string[] args)
    {
        this.Log("Simple Service Started");
        this.ScheduleService();
    }

    protected override void OnStop()
    {
        this.Log("Simple Service Stopped");
        this.Schedular.Dispose();
    }

    private Timer Schedular;

    public void ScheduleService()
    {
        try
        {
            Schedular = new Timer(new TimerCallback(SchedularCallback));
            // Code that schedules the Callback
        }
     }

    private void SchedularCallback(object e)
    {
        try
        {
                  // Scheduled Job code
         }
     }

现在我有另一个类似的要求,我必须触发另一封电子邮件,但其日程安排必须在2周内完成。有没有办法在同一项服务中安排这项工作,或者我必须写另一项服务?

3 个答案:

答案 0 :(得分:2)

我曾经在我的一个项目中做过类似的设计。 尝试使用基本摘要" ScheduledTask"定义您的计时行为的类,并由继承的任务类使用它。

以下是我为计时器所做的事情,我认为将其更改为计划程序只需要做些小工作。

internal abstract class TaskBase
{
    /// <summary>
    /// Task timer
    /// </summary>
    private readonly Timer _timer;

    /// <summary>
    /// Set refresh time
    /// </summary>
    protected int TimeRefreshSec { get; private set; }

    /// <summary>
    /// Loop of timePassed
    /// </summary>
    protected int TimePassed { get; private set; }

    protected TaskBase(double refreshInterval)
    {
        TimeRefreshSec = (int) refreshInterval / 1000;
        TimePassed = 0;

        _timer = new Timer(refreshInterval) { AutoReset = true };
        _timer.Elapsed += Tick;
    }

    private void Tick(object sender, ElapsedEventArgs e)
    {
        TimePassed += TimeRefreshSec;

        Tick();
    }

    public void Start()
    {
        ResetTimer();

        // Run the task once when starting instead of waiting for a full interval.
        Tick();
        OnStart();
    }

    public void Stop()
    {
        if (_timer.Enabled)
        {
            _timer.Stop();
            OnStop();
        }
    }

    protected virtual void ResetTimer()
    {
        TimePassed = 0;
        if (_timer.Enabled) _timer.Stop();
        _timer.Start();
    }

    /// <summary>
    /// Implement here a specific behavior when task is stopped.
    /// </summary>
    protected abstract void OnStop();

    /// <summary>
    /// Implement here a specific behavior when task is started.
    /// </summary>
    protected abstract void OnStart();

    /// <summary>
    /// This method is executed each time the task's timer has reached the interval specified in the constructor.
    /// Time counters are automatically updated.
    /// </summary>
    protected abstract void Tick();
}

和服务:

public partial class MyService : ServiceBase
{
    private readonly List<TaskBase> _tasks; 

    public MyService()
    {
        InitializeComponent();

        // Add in this list the tasks to run periodically.
        // Tasks frequencies are set in the corresponding classes.
        _tasks = new List<TaskBase>
        {
            new InheritingTask(),
            new OherInheritingTask()
        };
    }

    protected override void OnStart(string[] args)
    {
        try
        {
            _tasks.ForEach(t => t.Start());
        }
        catch (Exception ex)
        {
            Stop();
        }
    }

    protected override void OnStop()
    {
        _tasks.ForEach(t => t.Stop());
    }
}

编辑:

继承TaskBase的类的代码:

class InheritingTask: TaskBase
{
    public InheritingTask()
        : base(Settings.Default.InheritingTaskInterval) // In milliseconds
    {
        //TODO: Custom initialization here
    }

    protected override void Tick()
    {
        //TODO: Task logic here
    }

    protected override void OnStart()
    { }

    protected override void OnStop()
    { }

    protected override void ResetTimer()
    {
        //TODO: Custom reset logic here
        base.ResetTimer();
    }
}

答案 1 :(得分:1)

你可以很容易地制作一个在Schedular开始的第二个ScheduleService,它会在两周后启动,但Timer每周发射一次或两次是一种可怕的方式要做到这一点,如果计算机重新启动,您将丢失计时器,等待的电子邮件将不会被发送。

您需要一个类型的数据库来存储下一个事件应该触发以便重新启动程序,使用存储的库并为您安排Hangfire

答案 2 :(得分:1)

是的,您可以使用多线程实现此目的,例如通过TasksBackgroundworkers。有了这个,您可以在不同的线程上启动每个计时器,当计时器滴答时执行您的操作。建议在不同的线程上分离定时器和执行 - 例如,定时器1和2的后台工作者和执行1和2的后台工作者。