Конвертировать TimeSpan.TotalMilliseconds в long - PullRequest
2 голосов
/ 10 апреля 2011

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


Редактировать: очевидно, независимо от того, какую перегрузку 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);

Ответы [ 4 ]

3 голосов
/ 10 апреля 2011

Возможно, просто поработайте со свойством Ticks (Ticks - Long) и умножьте на TimeSpan.TicksPerMillisecond (постоянная, 10000 тиков в миллисекунду).

2 голосов
/ 10 апреля 2011
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

2 голосов
/ 10 апреля 2011

Поскольку (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);
0 голосов
/ 10 апреля 2011

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

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

Возможно, что-то вроде Quartz.Net может быть уместно?

...