Pages

Monday, March 7, 2011

All about .NET Timers - A Comparison

Threads and Timers are the most common things that you need for your application. Any work that needs to be done in background without intervening the work that is running in the foreground needed to be done using a Thread. We create Threads to delegate a long running process in background so that the UI remains unblocked. Timers on the other hand is a special module which runs after a certain interval of time in background. So you would think Timers will also create a new Thread in background and runs the module associated with it after a certain time. This is not always true.
In this post, I will compare most of the timers available with .NET right now, and later on discuss about DispatcherTimer in WPF.

Difference between Concurrency and Asynchrony?

Now if you look back when Microsoft introduced async CTP in PDC 2010,  or my own article on Async, it is clearly stated that Asynchrony and Concurrency are two different concepts. Asynchrony means running a job without blocking the Thread where it is working at. Concurrency is actually a special kind of asynchrony where it is achieved by creating a new Thread. Hence you can say, all sorts of concurrency is asynchrony while all asynchrony is not concurrency. You can have asynchrony without concurrency and it is really worth doing that, as you all know it is not good to put every work in Separate thread. ThreadPools could somewhat help by allowing you to manage threads but still Threads are for long running background processes, so beware to use it only when you absolutely require it.

Going ahead with this thought, lets compare the existing Timers.There are a number of Timers available with .NET before. Many of us might not know what is the basic difference between them. Lets put a comparative analysis on them one by one.



Comparison of Timers (Backtracking Thoughts) : 

System.Windows.Forms.Timer

Well, if you have ever worked in Windows based application in .NET, this object must be very well known to you. Windows.Forms.Timer is actually a normal Windows object which sends the messages directly to the Window messages which runs in background when no other foreground work is running. Hence, the Timer tick event is actually invoked directly into the UI thread and will invoke the EventHandler that we pass to it when the UI Thread is idle and processing window messages.

The usage :
private System.Windows.Forms.Timer WinTimer = new System.Windows.Forms.Timer();
 ObservableCollection<string> WinTimerList = new ObservableCollection<string>();
 private void btnwft_Click(object sender, RoutedEventArgs e)
 {
            this.WinTimer.Interval = 1000; //1 sec
            this.WinTimer.Tick += new EventHandler(WinTimer_Tick);
            this.WinTimer.Start();
            this.WinTimerList.Clear();
            this.lstwft.DataContext = this.WinTimerList;
 }

 void WinTimer_Tick(object sender, EventArgs e)
 {
    this.WinTimerList.Add(string.Format("Tick Generated from {0}", Thread.CurrentThread.Name));
 }

So basically, the object timer has a well defined structure, which call an event Tick after a certain time interval (in milliseconds).

Things to Remember: 
1. Runs in UI Thread.
2. Does not generate event when current UI Thread is busy.
3. It inserts a Window Message to invoke the method when Application.DoEvents occurs. Explicit call to Application.DoEvents  also generates the timer.

System.Timers.Timer

It is a special Timer that is designed for running in multi-threaded environment and also can be safely accessible from any thread. In fact this timer safely calls a new thread from the ThreadPool and uses ISynchronizeInvoke object to achieve this.

The Timers.Timer is also capable of calling itself in a thread which you specify. It exposes SynchronizingObject which needs an object of ISyncrhonizeInvoke. As window forms objects are itself implemented from ISynchronizeInvoke, it can be attached easily with UI Threads. Thus by setting the ISynchronizeObject to window, will automatically call the Timer callback in the UI thread. Strangely, WPF does not support ISynchronizeInvoke, hence you need to create one youself if you want to use it for WPF.

Usage :

private System.Timers.Timer TTTimer = new System.Timers.Timer();
ObservableCollection<string> TTimerList = new ObservableCollection<string>();
private void btntt_Click(object sender, RoutedEventArgs e)
{
    this.TTTimer.Interval = 1000; //1 sec
    this.TTTimer.Elapsed += new System.Timers.ElapsedEventHandler(TTTimer_Elapsed);
    this.TTTimer.Start();
    this.TTimerList.Clear();
    this.lsttt.DataContext = this.TTimerList;
}

void TTTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    string message = string.Format("Tick Generated from {0}", Thread.CurrentThread.Name);
    this.Dispatcher.Invoke((Action)delegate()
    {
        this.TTimerList.Add(message);
    });
}

So you can see the interface is almost the same, while instead of normal EventHandler the Timers.Timer actually passes an ElapsedEventHandler.

Even though this can be assigned to UI Thread using ISynchronizeInvoke, yet one major difference with Forms.Timer is that it will always queue a message on every timer interval elapsed even though the UI thread is busy. Hence if for 2 seconds you put a Thread.Sleep statement on both the timers, the Timers.Timer will be called twice after 2 seconds, while the Forms.Timer will queue only once.

Things to Remember:
1. It invokes the available thread in ThreadPool to run the interface.
2. ThreadSafe, each eventhandler has explicit locks.
3. Can be run in any thread using ISynchronizeObject.

The Internal
If you try to see the implementation detail of the Timer, you will see that the Timer actually puts a AutoResetEvent hooked with the Time for the next call. It invokes the callback using ISynchronizeObject.BeginInvoke. As Begin patterns actually creates a Thread from ThreadPool, it always uses a ThreadPool by default.


The Timer uses ChangeTimerNative to change time and gets the elapsed callback from AddTimeNative calls.


System.Threading.Timer

This Timer actually widely used and creates a new Thread inside it to run the callback. The Threding.Timer class is not ThreadSafe. So you should always device your code if you need ThreadSafe access of objects. Even, the class is not well structured and user friendly. It needs every input in its constructor to call a thread. As it always run on a new Thread from ThreadPool, you should not use it extensively as because even your UI Thread remains idle, it still wait to find other background Thread for its execution.

Usage:

private System.Threading.Timer STTimer;
ObservableCollection<string> STimerList = new ObservableCollection<string>();
private void btnstt_Click(object sender, RoutedEventArgs e)
{
    this.STTimer = new Timer(this.TimerElapsed, null, 1000, System.Threading.Timeout.Infinite);
            
    this.STimerList.Clear();
    this.lststt.DataContext = this.STimerList;
}
void TimerElapsed(object state)
{
    string message = string.Format("Tick Generated from {0}", Thread.CurrentThread.Name);
    this.Dispatcher.Invoke((Action)delegate()
    {
        this.STimerList.Add(message);
    });
}

Hence the constructor for Timer needs the callback method. The 2nd parameter is the state, which will be received to the callback. 3rd paramater represents the time after which the call will take place. 1000 means after 1 second the timer will invoke the Callback. TimeOut represents the periods, specify any numeric integers. 0 and Invinite will remove the subsequent calls to the method.

Like System.Timers.Timer, it also uses AddTimerNative call to get events from native environment. But it does always invoke the object in a new thread.

Things to Remember

1. Runs in a new thread always
2. Explcit call to period is required.
3. You can use Change method to change the properties after the Timer is invoked.
4. Class does not support inheritance
5. Purely used for numerical timing, where UI update is not or very less required.


DispatcherTimer 

In WPF,  the most common Timer that we use is DispatcherTimer. It runs on the Dispatcher Thread by default (UI Thread) and invokes the callback based on DispatcherPriority. DispatcherTimer is a special Timing object for WPF just like Forms.Timer in Windows. Dispatcher timer is not restricted to only one thread but rather runs every event on Dispatcher thread. If you are not aware of Dispatcher, you might want to read my WPF Tutorial series. DispatcherPriority is very useful when dealing with DispatcherTimer. The Threading model identifies the Priority of the Dispatcher callback and treats it accordingly.


DispatchrPriority :
Inactive  - throws an exception
SystemIdle - called when System is Idle or SystemIdle process takes maximum CPU time.
ApplicationIdle - Processes when Application is idle means UI thread is free.
ContextIdle - Processed when background operation is complete.
Background - Processed in background means processed only when all other non-idle operations are complete.
Send- Highest, and sent immediately.

There are other priorities too, which might be used.

Usage :
DispatcherTimer dispTimer = new DispatcherTimer(DispatcherPriority.SystemIdle);
ObservableCollection<string> stDispatcher = new ObservableCollection<string>();
private void btnDispatcher_Click(object sender, RoutedEventArgs e)
{
    dispTimer.Interval = TimeSpan.FromSeconds(1);
    dispTimer.Tick += new EventHandler(dispTimer_Tick);
    dispTimer.IsEnabled = true;
    stDispatcher.Clear();
    this.lstDispatcher.DataContext = stDispatcher;
}

void dispTimer_Tick(object sender, EventArgs e)
{
    this.stDispatcher.Add(string.Format("Tick Generated from {0}", Thread.CurrentThread.Name));
}

Now this will ensure that the dispTimer will be called after 1 second, and require the System to be Idle. If you are running complex operations , the Timer will not be called. Hence this gives you a chance to ensure that the timer will be called only when all other foreground operation is complete. Instead of that, if you specify DispatcherPriority.Send, it will be immediately processed.


The DispatcherTimer is elapsed on the Dispatcher Thread, and hence it is safe to use for any WPF applications.



The internals

If you see the internals of the DispatcherTimer, you will eventually find that the DispatcherTimer is also using the same native API to call the eventhandler. But the only difference is that , it uses DispatcherThread to process the code.


The hooks lets specify the various DispatcherEvents and allows it to Raise Timer event based on situation of the Dispatcher.

You should note, DispatcherTimer is ThreadSafe.

Download Sample code- 60 KB

Conclusion

In this brief case study, I think you might be clear about the usage of different timers. I hope to find feedbacks. Feel free to talk.

Thank you for reading.

2 comments:

  1. I think it's a great idea to do a comparison between all those timer classes. This article is one for my knowledge archive.
    Thanks

    ReplyDelete
  2. System.Threading.Timer uses the Threading Pool, it does not create a new thread for its calls.

    ReplyDelete

Please make sure that the question you ask is somehow related to the post you choose. Otherwise you post your general question in Forum section.