Нить спать / ждать до нового дня - PullRequest
11 голосов
/ 16 сентября 2011

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

Лучшим вариантом будет:

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

Ответы [ 5 ]

15 голосов
/ 16 сентября 2011

Не используйте Thread.Sleep для этого типа вещей.Используйте Таймер и рассчитайте продолжительность ожидания.

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Планировщик заданий для запуска вашей задачи в нужное время.Это будет намного надежнее, чем пытаться реализовать его самостоятельно в коде.

7 голосов
/ 16 сентября 2011

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

3 голосов
/ 16 сентября 2011

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

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);
0 голосов
/ 25 марта 2015

Вот так я усыплю нить до завтра 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);
0 голосов
/ 16 сентября 2011

С учетом двух предоставленных вами вариантов:

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

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

РЕДАКТИРОВАТЬ:

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

...