Question

I'm writing an app that will need to make use of Timers, but potentially very many of them. How scalable is the System.Threading.Timer class? The documentation merely say it's "lightweight", but doesn't explain further. Do these timers get sucked into a single thread (or very small threadpool) that processes all the callbacks on behalf of a Timer, or does each Timer have its own thread?

I guess another way to rephrase the question is: How is System.Threading.Timer implemented?

Was it helpful?

Solution

I say this in response to a lot of questions: Don't forget that the (managed) source code to the framework is available. You can use this tool to get it all: http://www.codeplex.com/NetMassDownloader

Unfortunately, in this specific case, a lot of the implementation is in native code, so you don't get to look at it...

They definitely use pool threads rather than a thread-per-timer, though.

The standard way to implement a big collection of timers (which is how the kernel does it internally, and I would suspect is indirectly how your big collection of Timers ends up) is to maintain the list sorted by time-until-expiry - so the system only ever has to worry about checking the next timer which is going to expire, not the whole list.

Roughly, this gives O(log n) for starting a timer and O(1) for processing running timers.

Edit: Just been looking in Jeff Richter's book. He says (of Threading.Timer) that it uses a single thread for all Timer objects, this thread knows when the next timer (i.e. as above) is due and calls ThreadPool.QueueUserWorkItem for the callbacks as appropriate. This has the effect that if you don't finish servicing one callback on a timer before the next is due, that your callback will reenter on another pool thread. So in summary I doubt you'll see a big problem with having lots of timers, but you might suffer thread pool exhaustion if large numbers of them are firing at the same timer and/or their callbacks are slow-running.

OTHER TIPS

I think you might want to rethink your design (that is, if you have control over the design yourself). If you're using so many timers that this is actually a concern for you, there's clearly some potential for consolidation there.

Here's a good article from MSDN Magazine from a few years ago that compares the three available timer classes, and gives some insight into their implementations:

http://msdn.microsoft.com/en-us/magazine/cc164015.aspx

Consolidate them. Create a timer service and ask that for the timers. It will only need to keep 1 active timer (for the next due call)...

For this to be an improvement over just creating lots of Threading.Timer objects, you have to assume that it isn't exactly what Threading.Timer is already doing internally. I'd be interested to know how you came to that conclusion (I haven't disassembled the native bits of the framework, so you could well be right).

^^ as DannySmurf says : Consolidate them. Create a timer service and ask that for the timers. It will only need to keep 1 active timer (for the next due call) and a history of all the timer requests and recalculate this on AddTimer() / RemoveTimer().

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top