Преобразовать временной интервал.TotalMilliseconds в long

#c# #.net #timespan

#c# #.net #timespan

Вопрос:

У меня есть некоторая DateTime переменная, и я хочу использовать System.Threading.Timer , чтобы дождаться наступления этого времени. Если время в прошлом, я хочу, чтобы таймер тикал немедленно.

Проблема в том, что TimeSpan.TotalMilliseconds это double , а самый большой тип времени ожидания таймера — это long .

Я попытался максимально увеличить время, необходимое для long.MaxValue использования этого кода:

 DateTime someUtcTime;
// Max due time to long.MaxValue
double doubleDueTime = Math.Min(
    (double)long.MaxValue,
    someUtcTime.Subtract(DateTime.UtcNow).TotalMilliseconds);

// Avoid negative numbers
long dueTime = Math.Max(0L, (long)doubleDueTime);

_timer.Change(dueTime, System.Threading.Timeout.Infinite);
  

но оказывается, что приведение long.MaxValue к удвоению и обратно к long приводит к отрицательному числу (в непроверенном коде curse). пожалуйста, пришлите мне код.


Редактировать: по-видимому, независимо от того, какую из Timer.Change перегрузок вы используете, все они ограничены 4294967294 ( UInt32.MaxValue - 1 ) миллисекундами.


Решение:

охватить оба крайних случая ( someUtcTime = DateTime.MaxValue; UtcNow = DateTime.MinValue; и наоборот).

 const uint MAX_SUPPORTED_TIMEOUT = uint.MaxValue - 1; //0xfffffffe

DateTime someUtcTime;
double doubleDueTime = (someUtcTime - DateTime.UtcNow).TotalMilliseconds;

// Avoid negative numbers
doubleDueTime = Math.Max(0d, doubleDueTime);

// Max due time to uint.MaxValue - 1
uint dueTime = (uint)Math.Min(MAX_SUPPORTED_TIMEOUT, doubleDueTime);
  

Комментарии:

1. Какова цель Math.Min((double)long.MaxValue части вашего кода?

2. «пожалуйста, пришлите мне код». — надеюсь, это юмор!

3. @Gabe: даты слишком далеко в будущем?

4. @Митч, это выглядело как простая задача на 2 минуты, но я не могу справиться с этим правильно. Разочарование привело меня к юмору. Это способ сказать: «Как бы вы, мои коллеги-ученые, решили эту головоломку?». Я надеюсь, что это вовсе не запрет юмора 🙂

5. Вас беспокоит временная метка на 300 миллионов лет в будущее?

Ответ №1:

Поскольку (DateTime.MaxValue - DateTime.MinValue).TotalMilliseconds равно 315537897600000 и long.MaxValue равно 9223372036854775807 ( long может представлять значение на 4 порядка больше, чем максимально возможное количество миллисекунд между любыми двумя DateTime значениями), у вас никогда не может быть слишком большого промежутка времени в будущем.

Этого будет достаточно:

 DateTime someUtcTime;
// Max due time to long.MaxValue
double doubleDueTime = (someUtcTime - DateTime.UtcNow).TotalMilliseconds;

// Avoid negative numbers
long dueTime = Math.Max(0L, (long)doubleDueTime);

_timer.Change(dueTime, System.Threading.Timeout.Infinite);
  

Комментарии:

1. Хорошая мысль, приятель. Хотя, как я отредактировал, ограничение есть UInt32.MaxValue - 1 , поэтому оно работает в течение ~ 50 дней в будущем . Я просто использую это @Marino’s.

Ответ №2:

Может быть, просто поработать со свойством Ticks (такты длинные) и умножить на TimeSpan.Количество тактов в миллисекунду (постоянная, 10000 тактов в миллисекунду).

Комментарии:

1. Похоже, что это сработает, но почему-то мне кажется неестественным использовать тики для реального времени. Может быть, это только у меня.

Ответ №3:

 Timespan timespan = someUtcTime.Subtract(DateTime.UtcNow);
long time = timespan.TotalMilliseconds <= long.MaxValue ? (long)timespan.TotalMilliseconds : -1;

if (time == -1) {
 sorry.nocando();
}
else {
 just.doit();
}
  

Кстати: при длинной миллисекунде у вас может быть временной интервал в 292471208 лет, я не думаю, что к тому времени ваш код будет использоваться. Существует вероятность того, что солнце уже пройдет мимо Марса и Земли больше не будет : D

Комментарии:

1. имейте в виду, что я предполагаю, что время в положительной прогрессии, Хокинг предполагает, что время может быть даже невообразимым или идти в обратном направлении, поэтому ‘-1’ может быть возможным значением времени 🙂

Ответ №4:

Таймеры предназначены для ожидания интервалов (обычно короче 24 часов).

Каково ваше предполагаемое использование? Планировщик обычно имеет список событий / задач и периодически каждую минуту (возможно, каждую секунду) проверяет, нужно ли запускать какие-либо задачи.

Возможно, что-то вроде Quartz.Net может быть подходящим?

Комментарии:

1. Это своего рода планировщик, но он настолько прост в использовании, что я не хочу связывать его со сторонними библиотеками.