Windows服务在指定时间运行函数

时间:2013-10-03 05:21:50

标签: c# timer windows-services

我想启动一项Windows服务,以便在特定时间每天运行一项功能。

我应该考虑采用什么方法来实现这个?定时器还是使用线程?

7 个答案:

答案 0 :(得分:64)

(1)首次启动时,将_timer.Interval设置为服务启动和调度时间之间的毫秒数。此样本设置的时间表为上午7点作为_scheduleTime = DateTime.Today.AddDays(1).AddHours(7);

(2)在Timer_Elapsed上,如果当前间隔不是24小时,则将_timer.Interval重置为24小时(以毫秒为单位)。

System.Timers.Timer _timer;
DateTime _scheduleTime; 

public WinService()
{
    InitializeComponent();
    _timer = new System.Timers.Timer();
    _scheduleTime = DateTime.Today.AddDays(1).AddHours(7); // Schedule to run once a day at 7:00 a.m.
}

protected override void OnStart(string[] args)
{           
    // For first time, set amount of seconds between current time and schedule time
    _timer.Enabled = true;
    _timer.Interval = _scheduleTime.Subtract(DateTime.Now).TotalSeconds * 1000;                                          
    _timer.Elapsed += new System.Timers.ElapsedEventHandler(Timer_Elapsed);
}

protected void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    // 1. Process Schedule Task
    // ----------------------------------
    // Add code to Process your task here
    // ----------------------------------


    // 2. If tick for the first time, reset next run to every 24 hours
    if (_timer.Interval != 24 * 60 * 60 * 1000)
    {
        _timer.Interval = 24 * 60 * 60 * 1000;
    }  
}

修改

有时人们希望将服务安排在 0 开始,而不是明天,所以他们会更改DateTime.Today.AddDays(0)。如果他们这样做并在过去设置时间,则会导致错误设置带有负数的区间。

//Test if its a time in the past and protect setting _timer.Interval with a negative number which causes an error.
double tillNextInterval = _scheduleTime.Subtract(DateTime.Now).TotalSeconds * 1000;
if (tillNextInterval < 0) tillNextInterval += new TimeSpan(24, 0, 0).TotalSeconds * 1000;
_timer.Interval = tillNextInterval;

答案 1 :(得分:6)

答案很好(我使用了你的代码),但这一行有一个问题:

_timer.Interval = _scheduleTime.Subtract(DateTime.Now).TotalSeconds * 1000;

如果DateTime.now晚于scheduleTime,您将变为负数,这将在分配给timer.Interval时生成异常。

我用过:

if (DateTime.now > scheduleTime)
    scheduleTime = scheduleTime.AddHours(24);

然后进行减法。

答案 2 :(得分:3)

使用Windows内置的任务计划程序(http://windows.microsoft.com/en-us/windows7/schedule-a-task)或Quartz.net。

除非......你有一项服务正在进行大量的其他处理,并且需要一直运行,在这种情况下,Timer可能是合适的。

答案 3 :(得分:2)

您确定,您需要一项每天只运行一次的服务吗?

也许Windows任务计划可能是更好的解决方案吗?

答案 4 :(得分:0)

<img id="imgRes" height="500px" width="770px"  />
   <div id="canvas" style="background-image:url(fimage/1.jpg)"><br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
</div> 
<button id="download">Download Pdf</button>

答案 5 :(得分:0)

你可以用线程和事件来做;不需要计时器。

using System;
using System.ServiceProcess;
using System.Threading;

partial class Service : ServiceBase
{
    Thread Thread;

    readonly AutoResetEvent StopEvent;

    public Service()
    {
        InitializeComponent();

        StopEvent = new AutoResetEvent(initialState: false);
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            StopEvent.Dispose();

            components?.Dispose();
        }

        base.Dispose(disposing);
    }

    protected override void OnStart(string[] args)
    {
        Thread = new Thread(ThreadStart);

        Thread.Start(TimeSpan.Parse(args[0]));
    }

    protected override void OnStop()
    {
        if (!StopEvent.Set())
            Environment.FailFast("failed setting stop event");

        Thread.Join();
    }

    void ThreadStart(object parameter)
    {
        while (!StopEvent.WaitOne(Timeout(timeOfDay: (TimeSpan)parameter)))
        {
            // do work here...
        }
    }

    static TimeSpan Timeout(TimeSpan timeOfDay)
    {
        var timeout = timeOfDay - DateTime.Now.TimeOfDay;

        if (timeout < TimeSpan.Zero)
            timeout += TimeSpan.FromDays(1);

        return timeout;
    }
}

答案 6 :(得分:-1)

如果是一天一次,为什么不使用任务计划程序? 如果要在几分钟内多次运行任务,则Windows服务非常有用。因此,如果要在特定时间运行程序,最好使用任务计划程序并在一天中的特定时间设置任务计划程序的事件。 我对任务计划程序及其完善性做了很多工作。 您可以在任务计划程序中设置程序的运行并设置运行它的间隔时间。 如果您希望每天每5分钟运行一次程序,则仍然可以使用任务计划程序及其更好的方法。