(1 item) |
|
(1 item) |
|
(5 items) |
|
(1 item) |
|
(1 item) |
|
(2 items) |
|
(2 items) |
|
(4 items) |
|
(1 item) |
|
(6 items) |
|
(2 items) |
|
(4 items) |
|
(1 item) |
|
(4 items) |
|
(2 items) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(2 items) |
|
(2 items) |
|
(5 items) |
|
(3 items) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(3 items) |
|
(1 item) |
|
(1 item) |
|
(2 items) |
|
(8 items) |
|
(2 items) |
|
(7 items) |
|
(2 items) |
|
(2 items) |
|
(1 item) |
|
(2 items) |
|
(1 item) |
|
(2 items) |
|
(4 items) |
|
(1 item) |
|
(5 items) |
|
(1 item) |
|
(3 items) |
|
(2 items) |
|
(2 items) |
|
(8 items) |
|
(7 items) |
|
(3 items) |
|
(7 items) |
|
(6 items) |
|
(1 item) |
|
(2 items) |
|
(5 items) |
|
(5 items) |
|
(7 items) |
|
(3 items) |
|
(7 items) |
|
(16 items) |
|
(10 items) |
|
(27 items) |
|
(15 items) |
|
(15 items) |
|
(13 items) |
|
(16 items) |
|
(15 items) |
Sometimes, code needs to do some stuff for a certain amount of time and then stop. I won't list all the reasons, but it's a common enough requirement.
There are many approaches to this. Sometimes, setting a timer to go off is an appropriate solution. However, there are costs involved with this - timers consume resource, and may result in thread switches. On the other hand, they're a whole lot cheaper than busy waiting. So unless you're creating a staggering number of timers, they're probably a good bet.
But sometimes, it's convenient to test for expiration of a timer in a loop. It's still possible to use a timer object in this case, but you have to make it set a boolean, and test that boolean. It's not actually all that convenient, and if you're already looping around for other reasons, timers may not be the best bet.
So a while ago, I wrote a little helper class that has this usage model:
WaitForTicks wait = new WaitForTicks(TimeSpan.FromSeconds(5)); while (!wait.TimeIsUp) { // Do Work... }
Internally, this class uses Environment.TickCount
internally. The tick count is the only reliable
way of doing this sort of waiting. Using DateTime
and TimeSpan
is arguably simpler,
but doesn't work if the system clock gets changed half way through a wait operation. Because
Environment.TickCount
increases monotonically, it is immune to system clock changes.
The only problem is that it spends about 25 out of every 50 days negative, and wraps round every
50 days. This is because the tick count is a 32 bit integer, and it counts milliseconds - that's roughly
how often such a count wraps. It's pretty easy to go wrong. For example, I wrote some code that uses the
Indy socket library to retrieve
some email, but it crashes if you use it on a day when the tick count is negative. (This is a bug in the
Indy library. They appear to wrap the tick count in a variable which doesn't permit negative numbers.
Although to be fair, there was a bug in the docs for TickCount
for ages, which said
incorrectly that it wraps from Int32.MaxValue
back down to zero, and never goes
negative. That's not true, and it would actually be really inconvenient if it were true.)
So I wrote a little helper class to wrap this stuff up, and deal reliably with wrap around. It's described in more detail here, or you can just go straight to the source code.