The only difference is that System.Threading.Timer sends a callback to the thread pool thread, rather than creating a new thread each time. If you need this to happen more than once during the life of your application, this will save the overhead of creating and destroying a group of threads (a process that is very resource intensive, as indicated in the article you are referring to), since it will simply be reuse threads in the pool, and if you have more than one timer working at the same time, this means that you will have fewer threads working at the same time (which will also save significant resources).
In other words, the Timer will be much more efficient. It can also be more accurate, as Thread.Sleep guaranteed to wait at least as long as you specify (the OS can put it to sleep much longer). Of course, the Timer will still not be exactly accurate, but the goal is to call the callback as close to the specified time as possible, while this is NOT necessarily the intention of Thread.Sleep .
Regarding the destruction of the Timer , the callback can take a parameter, so you can pass the Timer itself as a parameter and call Dispose in the callback (although I have not tried this - I think it is possible that the Timer might be blocked during the callback).
Change: No, I think you cannot do this, since you must specify the callback parameter in the Timer constructor itself.
Maybe something like this? (Again, haven't really tried this)
class TimerState { public Timer Timer; }
... and start the timer:
TimerState state = new TimerState(); lock (state) { state.Timer = new Timer((callbackState) => { action(); lock (callbackState) { callbackState.Timer.Dispose(); } }, state, millisecond, -1); }
The lock should prevent the timer callback from trying to free the timer before the Timer field has been set.
Application: As the commentator noted, if action() does something with the user interface, then it is better to use System.Windows.Forms.Timer , since it will perform a callback in the user interface thread. However, if this is not the case, and the point is Thread.Sleep versus Threading.Timer , Threading.Timer is the way to go.