Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

System.Threading.Timer in C# it seems to be not working. It runs very fast every 3 second

Tags:

c#

.net

timer

I've a timer object. I want it to be run every minute. Specifically, it should run a OnCallBack method and gets inactive while a OnCallBack method is running. Once a OnCallBack method finishes, it (a OnCallBack) restarts a timer.

Here is what I have right now:

private static Timer timer;  private static void Main() {     timer = new Timer(_ => OnCallBack(), null, 0, 1000 * 10); //every 10 seconds     Console.ReadLine(); }  private static void OnCallBack() {     timer.Change(Timeout.Infinite, Timeout.Infinite); //stops the timer     Thread.Sleep(3000); //doing some long operation     timer.Change(0, 1000 * 10);  //restarts the timer } 

However, it seems to be not working. It runs very fast every 3 second. Even when if raise a period (1000*10). It seems like it turns a blind eye to 1000 * 10

What did I do wrong?

like image 650
Alan Coromano Avatar asked Oct 09 '12 08:10

Alan Coromano


People also ask

What is System threading timer?

System. Threading. Timer, which executes a single callback method on a thread pool thread at regular intervals. The callback method is defined when the timer is instantiated and cannot be changed.

Does timer create new thread C#?

No, a timer runs in the thread in which it was created.

Is System threading timer thread safe?

Timer is not thread-safe.

Does timer run on main thread?

If a timer is fired on the main thread's run loop, you will probably have a problem with either the timer function or UI operation. For example, suppose you have triggered a timer. There is also a tableView in your app that shows a list to the user and the user is scrolling the table.


1 Answers

This is not the correct usage of the System.Threading.Timer. When you instantiate the Timer, you should almost always do the following:

_timer = new Timer( Callback, null, TIME_INTERVAL_IN_MILLISECONDS, Timeout.Infinite ); 

This will instruct the timer to tick only once when the interval has elapsed. Then in your Callback function you Change the timer once the work has completed, not before. Example:

private void Callback( Object state ) {     // Long running operation    _timer.Change( TIME_INTERVAL_IN_MILLISECONDS, Timeout.Infinite ); } 

Thus there is no need for locking mechanisms because there is no concurrency. The timer will fire the next callback after the next interval has elapsed + the time of the long running operation.

If you need to run your timer at exactly N milliseconds, then I suggest you measure the time of the long running operation using Stopwatch and then call the Change method appropriately:

private void Callback( Object state ) {    Stopwatch watch = new Stopwatch();     watch.Start();    // Long running operation     _timer.Change( Math.Max( 0, TIME_INTERVAL_IN_MILLISECONDS - watch.ElapsedMilliseconds ), Timeout.Infinite ); } 

I strongly encourage anyone doing .NET and is using the CLR who hasn't read Jeffrey Richter's book - CLR via C#, to read is as soon as possible. Timers and thread pools are explained in great details there.

like image 189
Ivan Zlatanov Avatar answered Sep 18 '22 23:09

Ivan Zlatanov