views:

2299

answers:

6

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 it's own thread?

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

A: 

probably be best to write a small POC and see how many you can spin up be before things go bad. I suspect that ~25 per process will be the max, but that's a WAG.

Booji Boy
+3  A: 

Reflector can help you show the implementation of that specific class.

Lars Truijens
+5  A: 

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

DannySmurf
+12  A: 

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.

Will Dean
A Priority Queue would probably be more efficient than a sorted list unless all the timers are added in bulk at the beginning, then sorted, and no more are added later.
Robert Lamb
Sure - 'a list sorted by time-until-expiry' could certainly be a kind of priority queue - I didn't mean to imply 'a list that has had a Sort operation run across it'
Will Dean
A: 

^^ 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().

Quibblesome
+1  A: 

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).

Will Dean