Вставить нить/подождать до нового дня

Я запускаю процесс в цикле, который имеет ограничение на количество операций, выполняемых в день. Когда он достигает этого предела, я в настоящее время проверяю время в цикле, чтобы увидеть, была ли новая дата.

Лучший вариант:

  • Продолжайте проверять время каждую секунду для новой даты.
  • Рассчитать количество секунд до полуночи и спящий период
  • Что-то еще?

Ответ 1

Не используйте 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 */ обратным вызовом, который возобновит вашу работу в указанный интервал.

Изменить: Как упоминалось в комментариях, есть много вещей, которые могут пойти не так, если вы принимаете "прошедшее время" приложение будет ждать, будет соответствовать реальное время. По этой причине, если для вас важно время, лучше использовать меньшие интервалы опроса, чтобы узнать, достигло ли часы времени, в которое вы хотите, чтобы ваша работа происходила.

Еще лучше было бы использовать планировщик задач Windows для запуска вашей задачи в нужное время. Это будет намного надежнее, чем пытаться реализовать его в коде.

Ответ 2

В Windows есть планировщик задач, который обрабатывает именно эту обязанность. Создайте программу, чтобы сделать то, что она должна делать. Затем настройте его как запланированную задачу.

Ответ 3

Просто рассчитайте период ожидания и запуска асинхронного таймера таким образом, чтобы избежать лишнего потребления процессора во время ожидания:

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);

Ответ 4

Учитывая два варианта, которые вы предоставили:

Есть 60 * 60 * 24 = 86 400 секунд в день, поэтому вы можете сделать много проверок, если вы нажмете предел раньше. Кроме того, ожидание ожидания является пустой тратой циклов процессора, и это замедлит все остальное, что работает.

Вы должны рассчитать количество секунд до полуночи и спать так долго (хотя я считаю, что параметр sleep имеет значение ms, а не s, поэтому может потребоваться простое преобразование).

EDIT:

Дополнительное преимущество вычисления спящего заключается в том, что если пользователь хочет обойти ваше ограничение, изменив часы, они не смогут (так как чтение часов в полночь не пробудит процесс, как при постоянной проверке), Однако, с лучшим пониманием того, как ваша программа работает внутри страны, пользователь может менять часы почти до полуночи каждый раз, когда они достигнут предела операций, заставляя поток просыпаться через несколько минут или даже несколько секунд. Это более сложная эксплуатация, чем это было бы возможно с вашим первым предложением, но это можно сделать.

Ответ 5

Вот как я делаю спящий поток до завтра 6AM

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);