633

I have been checking out some of the possible timers lately, and System.Threading.Timer and System.Timers.Timer are the ones that look needful to me (since they support thread pooling).

I am making a game, and I plan on using all types of events, with different intervals, etc.

Which would be the best?

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
TheAJ
  • 10,485
  • 11
  • 38
  • 57

9 Answers9

407

This article offers a fairly comprehensive explanation:

"Comparing the Timer Classes in the .NET Framework Class Library" - also available as a .chm file

The specific difference appears to be that System.Timers.Timer is geared towards multithreaded applications and is therefore thread-safe via its SynchronizationObject property, whereas System.Threading.Timer is ironically not thread-safe out-of-the-box.

I don't believe that there is a difference between the two as it pertains to how small your intervals can be.

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
David Andres
  • 31,351
  • 7
  • 46
  • 36
  • 82
    I think this excerpt is enlightening: "Unlike the System.Windows.Forms.Timer, the System.Timers.Timer class will, by default, call your timer event handler on a worker thread obtained from the common language runtime (CLR) thread pool. [...] The System.Timers.Timer class provides an easy way to deal with this dilemma—it exposes a public SynchronizingObject property. Setting this property to an instance of a Windows Form (or a control on a Windows Form) will ensure that the code in your Elapsed event handler runs on the same thread on which the SynchronizingObject was instantiated." – mico Oct 19 '10 at 09:53
  • 8
    According to the Thread Safety section in `Threading.Timer`'s [MSDN article](http://msdn.microsoft.com/en-us/library/system.threading.timer%28v=vs.110%29.aspx), it is perfectly thread-safe... – Pieter Oct 21 '12 at 18:33
  • 77
    `System.Threading.Timer` is as "ironically" not thread-safe as `System.Threading.Thread` and the threads obtained through the pool. Just because these classes do not hold your hand and manage the use of the `lock` keyword itself does not mean these classes aren't threadsafe. You might as well say `System.Threading.Thread` is not threadsafe, because it's exactly as true. – Kirk Woll Jan 04 '13 at 22:09
  • 11
    Also System.Timer.Timer interval can only be Int32 System.Threading.Timer interval can be up to Int64 – Brent Mar 12 '14 at 16:46
  • 4
    @Brent: That's not correct. The value can be specified as an Int64, but saying the "interval can be up to Int64" makes it sound like the full range of Int64 values can be used. In fact, the max value is only UInt32.MaxValue - 1, 4294967294. So it only gives twice the maximum value that the Int32-based versions provide. See the specification for NotSupportedException here: https://msdn.microsoft.com/en-us/library/3yb9at7c%28v=vs.110%29.aspx – RenniePet Nov 20 '15 at 01:09
  • [_"The .NET asynchronous Timer classes are perfectly thread-safe."_](http://stackoverflow.com/a/19577972/284240) – Tim Schmelter Jul 13 '16 at 13:13
  • 36
    It is unfortunate that this highly misleading (at best) answer is accepted and so highly up-voted. The only material statement in the answer itself is simply wrong. The `SynchronizingObject` does not make the timer object itself thread-safe. It just makes sure that _your code_ to handle the timer event is called in a specific thread (if you set that property appropriately). The timer object itself remains _not_ guaranteed to be thread-safe, as is clearly stated in the documentation. On the other hand, the `System.Threading.Timer` object _is_ specifically documented as being thread-safe. – Peter Duniho Nov 05 '17 at 19:58
  • 3
    @PeterDuniho I was about to comment the same. `SynchronizingObject` indeed is only to get back to the original thread context. Any one can easily write a timer callback method that accessed shared variables and make it thread unsafe. – Frank Q. Mar 11 '19 at 18:14
  • The answer is incorrect and misleading.`System.Threading.Timer` is thread safe, the other one is not. – Pingpong May 13 '20 at 08:23
  • It seems to me that the linked article is a bit outdated. As the System.Timers.Timer is built on a System.Threading.Timer, it is not 'safer' per see, as Peter explained. It is also worth to see the system.timer implementation is quite simple: https://source.dot.net/#System.ComponentModel.TypeConverter/System/Timers/Timer.cs,897683f27faba082 – EricBDev Jul 15 '21 at 08:57
216

System.Threading.Timer is a plain timer. It calls you back on a thread pool thread (from the worker pool).

System.Timers.Timer is a System.ComponentModel.Component that wraps a System.Threading.Timer, and provides some additional features used for dispatching on a particular thread.

System.Windows.Forms.Timer instead wraps a native message-only-HWND and uses Window Timers to raise events in that HWNDs message loop.

If your app has no UI, and you want the most light-weight and general-purpose .Net timer possible, (because you are happy figuring out your own threading/dispatching) then System.Threading.Timer is as good as it gets in the framework.

I'm not fully clear what the supposed 'not thread safe' issues with System.Threading.Timer are. Perhaps it is just same as asked in this question: Thread-safety of System.Timers.Timer vs System.Threading.Timer, or perhaps everyone just means that:

  1. it's easy to write race conditions when you're using timers. E.g. see this question: Timer (System.Threading) thread safety

  2. re-entrancy of timer notifications, where your timer event can trigger and call you back a second time before you finish processing the first event. E.g. see this question: Thread-safe execution using System.Threading.Timer and Monitor

Community
  • 1
  • 1
Tim Lovell-Smith
  • 15,310
  • 14
  • 76
  • 93
  • 3
    True the `System.Timers.Timer` uses a `System.Threading.Timer` internally. See [source code](https://referencesource.microsoft.com/#System/services/timers/system/timers/Timer.cs,133). – stomy May 10 '18 at 16:41
  • or in .NET / .NET Core: https://source.dot.net/#System.ComponentModel.TypeConverter/System/Timers/Timer.cs – EricBDev Jul 15 '21 at 09:16
126

In his book "CLR Via C#", Jeff Ritcher discourages using System.Timers.Timer, this timer is derived from System.ComponentModel.Component, allowing it to be used in design surface of Visual Studio. So that it would be only useful if you want a timer on a design surface.

He prefers to use System.Threading.Timer for background tasks on a thread pool thread.

Nate B.
  • 942
  • 11
  • 31
Hero
  • 1,423
  • 1
  • 10
  • 9
  • 45
    It can be used in a design surface - it doesn't mean it has to be, and there are no detrimental effects from not doing so. Reading the article in the earlier answer to this question, the Timers.Timer seems much more preferable to Threading.Timer. – Stephen Drew Nov 16 '11 at 12:38
  • 6
    Well, what is preferable depends on context, right? As I understand it, System.Threading.Timer executes the passed-in callback on a new worker thread from ThreadPool. Which, I assume is also why it's not necessarily thread-safe. Kinda makes sense. So, in theory, you wouldn't have to worry about the gruntwork of spinning up your own worker thread, as this timer will do it for you. Kinda seems ridiculously useful. – Finster Mar 27 '12 at 15:05
  • 8
    Using `System.Threading.Timer` is akin to using a thread pool or creating your own thread. *Of **course** these classes do not handle synchronization for you* -- that's your job! Neither a thread pool thread, your own thread, nor a timer callback will handle locking -- on what object and in what fashion and in what circumstances you need to lock requires good judgement and the threading version of the timer gives you the most flexibility and granularity. – Kirk Woll Jan 04 '13 at 22:07
  • 5
    -1 this answer is subjective or opinionated from the start and offers no concrete information on why System.Threading.Timer is preferred by Jeff Ritcher – Brian Ogden May 10 '16 at 20:35
  • I assume you folks are talking about Jeffrey Richter? – Martin Maat Apr 24 '23 at 08:38
66

Information from Microsoft about this (see Remarks on MSDN):

  • System.Timers.Timer, which fires an event and executes the code in one or more event sinks at regular intervals. The class is intended for use as a server-based or service component in a multithreaded environment; it has no user interface and is not visible at runtime.
  • 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. Like the System.Timers.Timer class, this class is intended for use as a server-based or service component in a multithreaded environment; it has no user interface and is not visible at runtime.
  • System.Windows.Forms.Timer (.NET Framework only), a Windows Forms component that fires an event and executes the code in one or more event sinks at regular intervals. The component has no user interface and is designed for use in a single-threaded environment; it executes on the UI thread.
  • System.Web.UI.Timer (.NET Framework only), an ASP.NET component that performs asynchronous or synchronous web page postbacks at a regular interval.

It is interesting to mention that System.Timers.Timer was deprecated with .NET Core 1.0, but was implemented again in .NET Core 2.0 (/ .NET Standard 2.0). The goal with .NET Standard 2.0 was that it should be as easy as possible to switch from the .NET Framework which is probably the reason it came back.

When it was deprecated, the .NET Portability Analyzer Visual Studio Add-In recommended to use System.Threading.Timer instead.

Looks like that Microsoft favors System.Threading.Timer before System.Timers.Timer.

EDIT NOTE 2018-11-15: I had to change my answer since the old information about .NET Core 1.0 was not valid anymore.

Tolga
  • 2,643
  • 1
  • 27
  • 18
ice1e0
  • 947
  • 7
  • 15
  • 2
    It seems it's true: https://github.com/npgsql/npgsql/issues/471#issuecomment-94104090 – Marco Sulla Jun 27 '16 at 08:55
  • @Taegost, its use is also limited -- see MSDN https://msdn.microsoft.com/en-us/library/system.timers.timer(v=vs.110).aspx and read the remarks about platform availability. – astrowalker Dec 18 '16 at 19:16
  • @astrowalker - Thanks for that, at the time I made the comment this answer had almost no detail. Since it now has the detail I was inquiring about, I deleted my comment. – Taegost Dec 19 '16 at 14:14
  • 1
    System.Timers.Timer is now supported in .NET Standard 2.0 and .NET Core 2.0 and above. https://learn.microsoft.com/en-us/dotnet/api/system.timers.timer (scroll to the end of article) – Lee Grissom Nov 11 '18 at 22:07
  • There is also [System.Windows.Threading.DispatcherTimer](http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatchertimer%28v=vs.110%29.aspx) per this [answer](https://stackoverflow.com/a/25669075). – SpeedCoder5 Aug 03 '19 at 22:10
51

One important difference not mentioned above which might catch you out is that System.Timers.Timer silently swallows exceptions, whereas System.Threading.Timer doesn't.

For example:

var timer = new System.Timers.Timer { AutoReset = false };
timer.Elapsed += (sender, args) =>
{
    var z = 0;
    var i = 1 / z;
};
timer.Start();

vs

var timer = new System.Threading.Timer(x =>
{
    var z = 0;
    var i = 1 / z;
}, null, 0, Timeout.Infinite);
stovroz
  • 6,835
  • 2
  • 48
  • 59
  • 1
    I recently hit this issue with Timers.Timer and it's been very painful... Any ideas how I could rewrite with Threading.Timer? http://stackoverflow.com/questions/41618324/windows-service-runs-but-stops-processing-after-two-days – Tez Wingfield Jan 13 '17 at 09:42
  • 11
    There is an empty catch in the source code. See the [System.Timers.Timer source code here](https://referencesource.microsoft.com/#System/services/timers/system/timers/Timer.cs,319) – stomy May 10 '18 at 16:30
  • Omgsh why MS programmers are not able to do same things really same? – xmedeko May 16 '18 at 11:18
  • 8
    Example does not explain how one swallows exceptions and the other doesn't. Could someone please fill in the details? – sean May 13 '19 at 17:22
24

I found a short comparison from MSDN

The .NET Framework Class Library includes four classes named Timer, each of which offers different functionality:

System.Timers.Timer, which fires an event and executes the code in one or more event sinks at regular intervals. The class is intended for use as a server-based or service component in a multithreaded environment; it has no user interface and is not visible at runtime.

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. Like the System.Timers.Timer class, this class is intended for use as a server-based or service component in a multithreaded environment; it has no user interface and is not visible at runtime.

System.Windows.Forms.Timer, a Windows Forms component that fires an event and executes the code in one or more event sinks at regular intervals. The component has no user interface and is designed for use in a single-threaded environment.

System.Web.UI.Timer, an ASP.NET component that performs asynchronous or synchronous web page postbacks at a regular interval.

default
  • 11,485
  • 9
  • 66
  • 102
3

From MSDN: System.Threading.Timer is a simple, lightweight timer that uses callback methods and is served by thread pool threads. It is not recommended for use with Windows Forms, because its callbacks do not occur on the user interface thread. System.Windows.Forms.Timer is a better choice for use with Windows Forms. For server-based timer functionality, you might consider using System.Timers.Timer, which raises events and has additional features.

Source

Greg Gum
  • 33,478
  • 39
  • 162
  • 233
1

The two classes are functionally equivalent, except that System.Timers.Timer has an option to invoke all its timer expiration callbacks through ISynchronizeInvoke by setting SynchronizingObject. Otherwise, both timers invoke expiration callbacks on thread pool threads.

When you drag a System.Timers.Timer onto a Windows Forms design surface, Visual Studio sets SynchronizingObject to the form object, which causes all expiration callbacks to be called on the UI thread.

Edward Brey
  • 40,302
  • 20
  • 199
  • 253
1

As other mentioned the link to MS Docs, one major difference between System.Timers.Timer and System.Threading.Timer is that System.Threading.Timer executes a single callback method defined once while the System.Timers.Timer reacts on events, so supports multiple subscribers which can be also removed.

As also mentioned above, the System.Timers.Timer is using a System.Threading.Timer internally, with e.g. the Enable=false disposing the internal timer, and re creates it on Enable=true / Start(): https://source.dot.net/#System.ComponentModel.TypeConverter/System/Timers/Timer.cs

EricBDev
  • 1,279
  • 13
  • 21