As you are probably already aware, there are 3 different timer classes available within the .NET framework.

  1. System.Timers.Timer
  2. System.Threading.Timer
  3. System.Windows.Forms.Timer

I was thinking about the applicability of each timer so I could decide which one to use within my application and I could not clearly remember the differences between System.Timers.Timer and System.Threading.Timer. Thankfully there is a great MSDN article that deals with exactly this subject. It's worth a read even though you might think you know all the differences. It will also remind you of the event re-entry issue that is often overlooked until a bug report ends up on your hands.

[Update]

I thought I'd be a bit more useful and provide a summary of the article here rather than force you to read the whole thing.

System.Windows.Forms.Timer

  • The elapsed event is fired on the UI thread so there is no need for synchronization code
  • Not accurate due to its dependency on the UI thread
  • If the UI thread is not available to process the timer's request, the elapsed event will not be fired (e.g. calling Thread.Sleep on the UI thread for a period of time longer than the timer interval will result in at least one timer event to not be fired)
  • No issues with event handler re-entry as everything is executing in one thread

System.Timers.Timer

  • Ideal for multi-threaded server applications as it is thread-safe and can be manipulated by multiple threads
  • The elapsed event is typically executed using a .NET ThreadPool thread.
  • Can be synchronized with UI controls so that the elapsed event is fired on the thread that created the controls, but if the UI thread is not available for processing the timer's request, the event will be fired when the thread because available again.
  • Event handler re-entry has to be catered for by temporarily suspending the timer.

System.Threading.Timer

  • It is not thread-safe and access through multiple threads has to make use of custom synchronization logic (e.g. lock() {})
  • The elapsed event is typically executed using a .NET ThreadPool thread.
  • Cannot be synchronized with UI controls so that the elapsed event is fired on the thread that created the controls. Such synchronization has to be achieved manually using the methods Control.Invoke and Control.BeginInvoke.
  • Event handler re-entry has to be catered for by temporarily suspending the timer.