I am using System.Threading Timers to poll sensors on different threads (one at a time was slow due to communication latency). It also allows the user change the polling rate by changing the timer period.
What I can't work out is what happens if timers don't finish before the next period. I wrote a test program, but it didn't really answer anything.
If I have a function that takes ~1.7s to run and call it every 10s, it finishes before the next one starts, and my CPU usage fluctuates between 13% (one core 100%) and 0%.
t = new Timer(doWork, null, 0, 10000);
private void doWork(object o)
{
for(int i = 0; i < numberItts; i++)
{
}
}
If I then lower the timer period to 1s I would expect it to either not execute a thread until the previous one is finished, or keep spawning new threads and the CPU usage would climb as more threads start before other finish. What actually happens is CPU usage fluctuates between 13% and 25%.
Changing the period to 500ms, the CPU useage then fluctuates between 38% and 50%. Surely at this point they should be starting much faster than they are ending.
How are these threads managed? What is limiting the amount created when the polling rate is faster than the rate at which threads can be finished?
Timer is not thread-safe.
start() is a function that is used to initialize a timer. To end or quit the timer, one must use a cancel() function. Importing the threading class is necessary for one to use the threading class. The calling thread can be suspended for seconds using the function time.
The application thread creates the timer, which waits one second and then executes the CheckStatus callback method every 250 milliseconds. The application thread then blocks until the AutoResetEvent object is signaled. When the CheckStatus callback method executes maxCount times, it calls the AutoResetEvent.
No, a timer runs in the thread in which it was created.
For Example, if a Delay Time is 2000 Milliseconds, then after the Timer creation, it will wait for 2 seconds before calling the Timer Callback. Unlike the Windows Forms’ Timer, the Threading Timer will invoke the Timer Callback in different thread
The threading class has a subclass called the class timer. In technical terms, we will create Timer objects when we need time-bound actions (methods), in technical terms. To use Timer class we will first have to import the time module. The args parameter is always preferably used to declare arguments to the functions to be called.
Although this may be true, the only constraint is that the Timer Component should belong to the Same UI thread. The Timer Component from the Timer name space if useful when we want to achieve the Mixture of UI and System Tasks.
The beauty of threading is that you can tell the computer to perform a task some other time or do it simultaneously. You can also execute the code simultaneously on different threads, making it extremely powerful. A timer class always runs in intervals.
Unlike System.Windows.Forms.Timer
, System.Threading.Timer
uses a thread pool and is not subject to being blocked if your timer handler takes longer than the timer interval to complete.
So if your doWork
takes about "~1.7s" to complete and your timer interval is one second, you would expect to see multiple concurrent threads entering doWork
.
How are these threads managed? What is limiting the amount created when the polling rate is faster than the rate at which threads can be finished?
That's all handled by the Timer
class and associated thread pool.
MSDN has this to say:
The callback method executed by the timer should be reentrant, because it is called on ThreadPool threads. The callback can be executed simultaneously on two thread pool threads if the timer interval is less than the time required to execute the callback, or if all thread pool threads are in use and the callback is queued multiple times. more...
So given this piece of code, where the timer interval is 2 seconds and handler processing time is 1 second, we can expect the same thread each time because its generally better to re-use the same thread than spin up a new one:
class Program
{
static void Main(string[] args)
{
var t = new Timer(doWork, null, 0, 1000);
Console.WriteLine("Press any key to quit");
Console.ReadKey();
}
private static void doWork(object o)
{
Console.WriteLine("Thread: {0}", Environment.CurrentManagedThreadId);
// simulate lengthy process
Thread.Sleep(1000);
}
}
Changing the interval and processing time to 1 second, leads to random threads due to the slight overlap.
Changing the interval to 200ms and keeping processing time to 1 second results in a higher number of worker threads than before. The reason being is that the thread pool has realised that delegates are taking longer to complete than the timer interval so it tries to keep up:
I think the following happens for a timer period of 1s:
I.e. still the threads are processed faster than they are created. Even for 500ms this will be true.
I think the behaviour you expected will occur when you reduce the timer period to a value < 1.7s/8 = ~0.2125s (Assuming you have 8 processors available doing nothing but process your threads which takes them 1.7s.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With