Reputation: 4761
I have some DateTime
variable, and I want to use System.Threading.Timer
to wait until this time arrive. If time is in the past I want the timer to tick immediately.
The problem is TimeSpan.TotalMilliseconds
is double
and timer due time biggest type islong
.
I've tried to max the due-time to long.MaxValue
using this code:
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);
but it turns out that casting long.MaxValue
to double and back to long result a negative number (in unchecked code of curse). plz send me teh codez.
Edit: apparently, no matter which of Timer.Change
overload you use, they are all limited to 4294967294 (UInt32.MaxValue - 1
) milliseconds.
cover both extreme cases (someUtcTime = DateTime.MaxValue; UtcNow = DateTime.MinValue;
and vice versa).
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);
Upvotes: 4
Views: 14434
Reputation: 7342
Timespan timespan = someUtcTime.Subtract(DateTime.UtcNow);
long time = timespan.TotalMilliseconds <= long.MaxValue ? (long)timespan.TotalMilliseconds : -1;
if (time == -1) {
sorry.nocando();
}
else {
just.doit();
}
BTW: with a long millisecond you can have a timespan of 292471208 years, I don't think your code will be used by then. There is possibility that the sun will already have expanded past mars and earth is no more :D
Upvotes: 2
Reputation: 86718
Since (DateTime.MaxValue - DateTime.MinValue).TotalMilliseconds
is 315537897600000 and long.MaxValue
is 9223372036854775807 (long
can represent a value 4 orders of magnitude larger than the largest possible number of milliseconds between any two DateTime
values), you can never have a time too far in the future.
This will suffice:
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);
Upvotes: 4
Reputation: 300529
Timers are designed to wait for intervals (typically shorter than 24 hours).
What is your intended use? A scheduler would typically have a list of events/tasks, and periodically every minute (maybe every second) check to see if any tasks need to be fired.
Perhaps something like Quartz.Net might be appropriate?
Upvotes: 0
Reputation: 8074
Maybe just work with the Ticks property (Ticks are Long) and multiply by TimeSpan.TicksPerMillisecond (constant, 10,000 ticks per millisecond).
Upvotes: 4