线程睡眠/等到新的一天

时间:2011-09-16 13:52:31

标签: c# multithreading datetime thread-sleep

我正在循环中运行一个进程,它对每天的操作数量有限制。当它达到这个限制时,我现在已经检查了循环中的时间,看它是否是一个新的日期。

最好的选择是:

  • 继续检查新日期的每秒时间
  • 计算午夜之前的秒数并睡眠那段时间
  • 别的什么?

5 个答案:

答案 0 :(得分:15)

不要将Thread.Sleep用于此类事情。使用Timer并计算您需要等待的持续时间。

var now = DateTime.Now;
var tomorrow = now.AddDays(1);
var durationUntilMidnight = tomorrow.Date - now;

var t = new Timer(o=>{/* Do work*/}, null, TimeSpan.Zero, durationUntilMidnight);

/* Do Work */委托替换为将以指定间隔恢复工作的回调。

编辑如评论中所述,there are many things that can go wrong如果您认为应用程序等待的“已用时间”将与实际时间相匹配。因此,如果时间对您很重要,最好使用较小的轮询间隔来确定时钟是否已达到您希望工作发生的时间。

更好的方法是使用Windows任务计划程序在所需的时间运行您的任务。这比尝试在代码中自己实现它更可靠。

答案 1 :(得分:7)

Windows有一个task scheduler来处理这个职责。创建程序以执行它应该执行的操作。然后将其设置为计划任务。

答案 2 :(得分:3)

只需计算一段等待时间并以这种方式运行异步计时器就可以避免在等待时消耗额外的CPU:

var nextDateStartDateTime = DateTime.Now.AddDays(1).Subtract(DateTime.Now.TimeOfDay);
double millisecondsToWait = (nextDateStartDateTime - DateTime.Now).TotalMilliseconds;

System.Threading.Timer timer = new Timer(
    (o) => { Debug.WriteLine("New day comming on"); },
    null,
    (uint)millisecondsToWait
    0);

答案 3 :(得分:0)

考虑您提供的两个选项:

每天有60 * 60 * 24 = 86,400秒,因此如果您提前达到限制,您可能会进行大量检查。此外,忙碌的等待会浪费CPU周期,并且会减慢正在运行的所有其他内容。

你应该计算到午夜之前的秒数并且睡眠时间很长(尽管我认为睡眠参数需要ms而不是s,因此可能需要进行简单的转换。)

修改

计算然后休眠的另一个好处是,如果用户想要通过更改时钟来绕过限制,他们将无法(因为午夜的时钟读数不会像连续检查那样唤醒过程) 。但是,通过更好地理解程序在内部的工作方式,用户可以在每次达到操作限制时将时钟更改为接近午夜,从而导致线程在几分钟甚至几秒钟内唤醒。与你的第一个建议相比,这是一个更复杂的利用,但它可以做到。

答案 4 :(得分:-1)

这是我让线程睡到明天早上6点的方式

minutesToSleep = (int)(new DateTime(DateTime.Now.AddDays(1).Year, DateTime.Now.AddDays(1).Month, DateTime.Now.AddDays(1).Day, 6, 0, 0) - DateTime.Now).TotalMinutes;
Console.WriteLine("Sleeping for {0} minutes (until tomorrow 6AM)", minutesToSleep);