Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何安排C#Windows服务每天执行任务?_C#_Windows Services_Scheduling_Scheduled Tasks - Fatal编程技术网

如何安排C#Windows服务每天执行任务?

如何安排C#Windows服务每天执行任务?,c#,windows-services,scheduling,scheduled-tasks,C#,Windows Services,Scheduling,Scheduled Tasks,我有一个用C#(.NET1.1)编写的服务,希望它在每晚午夜执行一些清理操作。我必须保留服务中包含的所有代码,那么最简单的方法是什么?使用Thread.Sleep()并检查时间滚动?我实现这一点的方法是使用计时器 运行服务器计时器,让它每60秒检查一次小时/分钟 如果是正确的小时/分钟,则运行您的流程 实际上,我已经将其抽象为一个基类,我称之为OnceDayRunner 让我把代码整理一下,然后贴在这里 private void OnceADayRunnerTimer_Elapsed(o

我有一个用C#(.NET1.1)编写的服务,希望它在每晚午夜执行一些清理操作。我必须保留服务中包含的所有代码,那么最简单的方法是什么?使用
Thread.Sleep()
并检查时间滚动?

我实现这一点的方法是使用计时器

运行服务器计时器,让它每60秒检查一次小时/分钟

如果是正确的小时/分钟,则运行您的流程

实际上,我已经将其抽象为一个基类,我称之为OnceDayRunner

让我把代码整理一下,然后贴在这里

    private void OnceADayRunnerTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        using (NDC.Push(GetType().Name))
        {
            try
            {
                log.DebugFormat("Checking if it's time to process at: {0}", e.SignalTime);
                log.DebugFormat("IsTestMode: {0}", IsTestMode);

                if ((e.SignalTime.Minute == MinuteToCheck && e.SignalTime.Hour == HourToCheck) || IsTestMode)
                {
                    log.InfoFormat("Processing at: Hour = {0} - Minute = {1}", e.SignalTime.Hour, e.SignalTime.Minute);
                    OnceADayTimer.Enabled = false;
                    OnceADayMethod();
                    OnceADayTimer.Enabled = true;

                    IsTestMode = false;
                }
                else
                {
                    log.DebugFormat("Not correct time at: Hour = {0} - Minute = {1}", e.SignalTime.Hour, e.SignalTime.Minute);
                }
            }
            catch (Exception ex)
            {
                OnceADayTimer.Enabled = true;
                log.Error(ex.ToString());
            }

            OnceADayTimer.Start();
        }
    }
该方法的核心是e.SignalTime.Minute/Hour检查


那里有用于测试等的钩子。但这就是您的计时器运行的样子。

它必须是实际的服务吗?您可以只使用windows控制面板中的内置计划任务。

日常任务吗?听起来它应该只是一个计划任务(控制面板)-这里不需要服务。

签出。您可以在Windows服务中使用它。它允许您根据配置的计划运行作业,甚至支持简单的“cron-job”语法。我在这方面取得了很多成功

下面是其用法的一个快速示例:

// Instantiate the Quartz.NET scheduler
var schedulerFactory = new StdSchedulerFactory();
var scheduler = schedulerFactory.GetScheduler();

// Instantiate the JobDetail object passing in the type of your
// custom job class. Your class merely needs to implement a simple
// interface with a single method called "Execute".
var job = new JobDetail("job1", "group1", typeof(MyJobClass));

// Instantiate a trigger using the basic cron syntax.
// This tells it to run at 1AM every Monday - Friday.
var trigger = new CronTrigger(
    "trigger1", "group1", "job1", "group1", "0 0 1 ? * MON-FRI");

// Add the job to the scheduler
scheduler.AddJob(job, true);
scheduler.ScheduleJob(trigger);

我不会使用Thread.Sleep()。使用计划任务(如其他人所述),或在服务中设置计时器,定期(例如每10分钟)启动,并检查自上次运行以来日期是否更改:

private Timer _timer;
private DateTime _lastRun = DateTime.Now.AddDays(-1);

protected override void OnStart(string[] args)
{
    _timer = new Timer(10 * 60 * 1000); // every 10 minutes
    _timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
    _timer.Start();
    //...
}


private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    // ignore the time, just compare the date
    if (_lastRun.Date < DateTime.Now.Date)
    {
        // stop the timer while we are running the cleanup task
        _timer.Stop();
        //
        // do cleanup stuff
        //
        _lastRun = DateTime.Now;
        _timer.Start();
    }
}
private Timer\u Timer;
private DateTime _lastRun=DateTime.Now.AddDays(-1);
启动时受保护的覆盖无效(字符串[]args)
{
_定时器=新定时器(10*60*1000);//每10分钟
_timer.appeated+=新系统.Timers.ElapsedEventHandler(timer_appeated);
_timer.Start();
//...
}
私有无效计时器(对象发送器,System.Timers.ElapsedEventArgs e)
{
//忽略时间,只比较日期
如果(_lastRun.Date
我建议您使用计时器,但将其设置为每45秒检查一次,而不是每分钟检查一次。否则,您可能会遇到负载过重时,无法检查特定分钟的情况,因为在计时器触发时间和代码运行并检查当前时间之间,您可能已经错过了目标分钟。

正如其他人已经编写的,计时器是您描述的场景中的最佳选项

根据您的具体要求,可能不需要每分钟检查一次当前时间。 如果您不需要完全在午夜执行操作,但仅在午夜后一小时内执行,则可以只检查日期是否已更改

如果您希望在午夜执行操作的原因是您希望计算机上的工作负载较低,请务必小心:其他人通常也会做出相同的假设,突然之间,您会在凌晨0:00到0:01之间启动100个清理操作

在这种情况下,你应该考虑在不同的时间开始清理。我通常不是在下班时间做这些事情,而是在半小时内(我个人喜欢凌晨1:30)

试试这个:

public partial class Service : ServiceBase
{
    private Timer timer;
    public Service()
    {
        InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
        SetTimer();
    }

    private void SetTimer()
    {
        if (timer == null)
        {
            timer = new Timer();
            timer.AutoReset = true;
            timer.Interval = 60000 * Convert.ToDouble(ConfigurationManager.AppSettings["IntervalMinutes"]);
            timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
            timer.Start();
        }
    }

    private void timer_Elapsed(object source, System.Timers.ElapsedEventArgs e)
    {
        //Do some thing logic here
    }

    protected override void OnStop()
    {
        // disposed all service objects
    }
}

您也可以在此处尝试TaskSchedulerLibrary


实现抽象类
AbstractScheduledTask
并调用
ScheduleUtilityFactory.AddScheduleTaskToBatch
静态方法对于那些发现上述解决方案不起作用的人来说,这是因为类中可能有一个
this
,这意味着一个扩展方法,正如错误消息所说,只有在非泛型静态类上才有意义。你的类不是静态的。作为一种扩展方法,这似乎没有什么意义,因为它作用于所讨论的实例,所以删除
This

由于服务器繁忙而产生的轻微延迟可能会导致它错过小时+分钟。真的。当我这样做时,我检查:现在的时间是否大于00:00?如果是的话,我上次做这份工作已经超过24小时了吗?如果是这样,请运行该作业,否则请再次等待。由于该服务已经存在,因此在那里添加功能可能更容易。将这样的狭义服务转换为控制台应用程序应该很简单。他已经说过,“我必须保留服务中包含的所有代码”。我觉得没有必要质疑最初的要求。这要视情况而定,但有时有很好的理由在计划任务上使用服务。+1:因为你总是需要从各个方面来看待你的问题。如果我真的每天只有一个任务要运行,那么我想一个简单的控制台应用程序运行一个计划任务就可以了。我的观点是,这取决于具体情况,在我看来,说“不要使用windows服务”不是一个有用的答案。如果你不检查以确保它没有运行过一次,那么如果你检查45秒,你可能会两次点击00:00。这一点很好。通过在检查过程结束时调用Sleep(15000),可以避免此问题。(或者16000毫秒,为了安全起见;-)我同意,不管你选择的计时器持续时间是多少,你都应该检查它是否已经运行。一个很好的建议——只要你做一些比基本计时器稍微复杂的事情,你就应该看看石英。石英非常容易使用,我认为即使是一个超级简单的任务,去用它吧。它将提供轻松调整调度的能力。超级简单不是真的吗?大多数新手在这里都会遇到这个问题,把计时器设置为午夜过期,而不是每分钟都醒来检查时间,这不是更有意义吗?@Kibbee:也许如果服务不是在午夜运行(不管什么原因)