C# 将代码设置为每24小时运行一次

C# 将代码设置为每24小时运行一次,c#,C#,对于工作中的一个辅助项目,我尝试在某个特定时间每24小时运行一段代码。我的老板让我使用无限循环而不是C#的计时器类,所以这是我正在处理的主要约束。我的问题是,代码将在前24小时内工作(即,它将在我设置代码的那天运行代码),但之后它将不会更新。我没有被抛出任何异常或错误,所以我假设这只是我的逻辑问题 以下是我现在掌握的代码要点 int i = 0; while (true) { DateTime currentdate = DateTime.Now; String time = c

对于工作中的一个辅助项目,我尝试在某个特定时间每24小时运行一段代码。我的老板让我使用无限循环而不是C#的计时器类,所以这是我正在处理的主要约束。我的问题是,代码将在前24小时内工作(即,它将在我设置代码的那天运行代码),但之后它将不会更新。我没有被抛出任何异常或错误,所以我假设这只是我的逻辑问题

以下是我现在掌握的代码要点

int i = 0;
while (true)
{
    DateTime currentdate = DateTime.Now;
    String time = currentdate.ToString("HH:mm");

    if ((time == "23:50" || time == "23:51") && i == 0)
    {
        HistoricalAverageCollection HAC = new HistoricalAverageCollection();
        HAC.ExecHAC();

        HistoricalAverageError HAE = new HistoricalAverageError();
        HAE.ExecHAE();
        FourWeekAverageCollection FWAC = new FourWeekAverageCollection();
        FWAC.ExecFWAC();
        FourWeekAverageError FWAE = new FourWeekAverageError();
        FWAE.ExecFWAE();

        DomainsReturningZeroTwentyFourHours DRZ = 
            new DomainsReturningZeroTwentyFourHours();
        DRZ.ExecDomainsReturningZero();

        context.SaveChanges();

        //Program should update every 24 horus
        i = 1;

        Console.Write("Updated The Historical Averages In The Data Base at...");
        Console.Write(DateTime.Now);
        Console.WriteLine("i is -> {0}", i);
        Console.Read();
    }
    else if (time == "06:00" && i == 1)
    {
        ReportEmail Report = new ReportEmail();
        Report.CreateAndSendReport();
        i = 0;
        Console.Write("counter reset. I is now -> {0} /n Email Sent",i);
        Console.Read();
    }
}
代码设置为在晚上11:50调用一组tsql存储过程,然后在早上6点根据这些数据发送电子邮件报告。然而,它只会运行一次,我发现自己在一两天后的早上醒来,发现没有发送电子邮件


任何帮助都将不胜感激:)

保留一个时间变量,该变量指示要运行的“下一个”日期时间

在您的循环中,只需检查当前时间是否在该时间之后,然后运行您的代码。。然后将变量重置为下一天,即现在+24小时

另一个答案表明问题在于线路:

Console.Read();

需要删除的

我支持许多建议其他更适合的方法的评论,但我相信您的问题在于:

Console.Read();
从文件中:

当您键入输入字符时,Read方法阻止其返回;信息技术 按Enter键时终止


因此,它将阻止等待一个永远不会出现的条目。

如果您真的想在不使用计时器或现有调度程序设施的情况下手动完成这一切,我建议您更严格一点,自己构建一个简单的任务调度程序类。您将需要的部件:

  • 用于存储每个任务的类,其中包括要为任务执行的代码以及每个任务应该运行的时间安排
  • 此类任务的列表
  • 从任务列表中计算下一个截止日期的方法,这样您就知道要睡多长时间了
  • 要睡眠的信号量lim(而不是
    Thread.sleep()
    • 使用信号量LIM,因为如果信号量从未释放,它将通过向其传递等待时间来充当
      线程.Sleep()
      ;但这也是因为,如果调度程序确定已添加新任务,并且应该唤醒它以重新评估下一个截止日期,则可以手动释放它
我建议您将截止日期存储在UTC中,并使用UTC时间完成大部分时间计算工作,这样就不会混淆时区更改或DST

你也应该考虑到直到下一个截止日期才睡觉,以防PC系统时间有NTP更新。考虑一次睡眠最多1小时。

让您开始学习的一些要点:

public void Run()
{
    this.running = true;

    do
    {
        DateTime nextDeadlineUtc;
        ScheduledTask nextTask;
        bool deadlineExpired;

        nextDeadlineUtc = ComputeNextDeadline( out nextTask );

        deadlineExpired = WaitForDeadline( nextDeadlineUtc );

        if( deadlineExpired )
        {
            // We hit the deadline. Execute the task and move on.
            nextTask.Execute();
        }
        else
        {
            // We were woken up before the deadline expired. That means either we're shutting
            // down, or we need to recompute our next deadline because the schedule changed.
            // To deal with this, just do nothing. We'll loop back around and either find out
            // we're being asked to stop, or we'll recompute the next deadline.
        }
    }
    while( this.running );
}

/// <summary>
/// Sleeps until the deadline has expired.
/// </summary>
/// <param name="nextDeadlineUtc">The next deadline, in UTC</param>
/// <returns>
/// True if the deadline has elapsed; false if the scheduler should re-examine its next deadline.
/// </returns>
private bool WaitForDeadline( DateTime nextDeadlineUtc )
{
    TimeSpan wait;
    bool incompleteDeadline;
    bool acquired;

    wait = ComputeSleepTime( nextDeadlineUtc, out incompleteDeadline );

    acquired = this.waiter.Wait( wait );

    if( acquired || incompleteDeadline )
    {
        // Either:
        // - We were manually woken up early by someone releasing the semaphore.
        // - The timeout expired, but that's because we didn't wait for the complete time.
        // 
        // Either way, the deadline didn't expire.
        return false;
    }
    else
    {
        // The deadline occurred. 
        return true;
    }
}

private TimeSpan ComputeSleepTime( DateTime nextDeadlineUtc, out bool incompleteDeadline )
{
    TimeSpan totalRemaining = nextDeadlineUtc - DateTime.UtcNow;

    if( totalRemaining.Ticks < 0 )
    {
        // Were already out of time.
        incompleteDeadline = false;
        return TimeSpan.FromTicks( 0 );
    }
    else if( totalRemaining.TotalHours <= 1.01 )
    {
        // Just sleep the whole of the remainder.
        incompleteDeadline = false;
        return totalRemaining;
    }
    else
    {
        // More than one hour to sleep. Sleep for at most one hour, but tell the sleeper that
        // there's still more time left.
        incompleteDeadline = true;
        return TimeSpan.FromHours( 1.0 );
    }
}
public void Run()
{
这是真的;
做
{
DateTime nextDeadlineUtc;
计划任务下一个任务;
布尔死亡线已过期;
nextDeadlineUtc=计算截止日期(超出nextTask);
deadlineExpired=WaitForDeadline(nextDeadlineUtc);
如果(死线过期)
{
//我们赶上了最后期限。完成任务,继续前进。
Execute();
}
其他的
{
//我们在截止日期前被叫醒了。这意味着要么我们要关门
//下一步,否则我们需要重新计算下一个截止日期,因为日程改变了。
//为了解决这个问题,我们什么也不做,我们会回过头来看看
//我们被要求停止,否则我们将重新计算下一个截止日期。
}
}
当(这个)运行时;
}
/// 
///睡到最后期限结束。
/// 
///下一个截止日期(UTC)
/// 
///如果截止日期已过,则为True;如果计划程序应重新检查其下一个截止日期,则为false。
/// 
专用布尔WaitForDeadline(日期时间下一个日期UTC)
{
时间跨度等待;
布尔不完全截止期;
布尔获得性;
等待=ComputeSleepTime(下一个截止日期UTC,超出未完成的截止日期);
获得=这个。服务员。等等(等等);
如果(获得| |未完成截止日期)
{
//要么:
//-我们很早就被释放信号灯的人手动叫醒了。
//-超时已过期,但这是因为我们没有等待完整的时间。
// 
//不管怎样,最后期限都没有到期。
返回false;
}
其他的
{
//截止日期到了。
返回true;
}
}
专用时间跨度计算时间(DateTime nextDeadlineUtc,out bool Uncomplete Deadline)
{
TimeSpan totalRemaining=nextDeadlineUtc-DateTime.UtcNow;
如果(剩余总刻度<0)
{
//我们已经没时间了。
不完全截止日期=假;
返回TimeSpan.FromTicks(0);
}

否则如果(totalRemaining.TotalHours)您不使用计划任务的原因是什么?您的老板不想使用Windows任务计划程序的原因是什么?这正是它的目的。哈哈!您知道您不必整夜等待吗?只要在醒着的时候将时间更改为值,然后检查出了什么问题。@Botonomous,因为这是错误的计划任务是做什么用的?我想每天运行一个东西。我想知道我是否可以计划它?如果计划改变了,为什么程序员要参与其中?即使出于某种原因,你不会使用计划任务,也不会使用.NET中的某个计时器类,至少在循环中设置一个睡眠,这样它就不会不断地破坏进程没有什么好的理由。我也更喜欢使用Windows任务调度程序,但不管出于什么原因,这并不理想。该程序实际上并不占用太多资源,所以我认为这不是什么大问题。好的,但由于您只检查分钟,您可以放置
线程。睡眠(60000);
插入您的代码,这样它就不会不必要地运行。这会停止thre