I have a method which should be delayed from running for a specified amount of time.
Should I use
Thread thread = new Thread(() => { Thread.Sleep(millisecond); action(); }); thread.IsBackground = true; thread.Start();
Or
Timer timer = new Timer(o => action(), null, millisecond, -1);
I had read some articles about how using Thread.Sleep is bad design. But I don’t really understand why.
However, for using Timer, Timer has a dispose method. Since the execution is delayed, I don’t know how to dispose the Timer. Do you have any suggestions?
Or, if you have an alternative suggestion for delaying code execution, that would also be appreciated.
One difference is that
System.Threading.Timerdispatches the callback on a thread pool thread, rather than creating a new thread every 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 bunch of threads (a process which is very resource intensive, as the article you reference points out), since it will just reuse threads in the pool, and if you will have more than one timer going at once it means you will have fewer threads running at once (also saving considerable resources).In other words,
Timeris going to be much more efficient. It also may be more accurate, sinceThread.Sleepis only guaranteed to wait at LEAST as long as the amount of time you specify (the OS may put it to sleep for much longer). Granted,Timeris still not going to be exactly accurate, but the intent is to fire the callback as close to the specified time as possible, whereas this is NOT necessarily the intent ofThread.Sleep.As for destroying the
Timer, the callback can accept a parameter, so you may be able to pass theTimeritself as the parameter and call Dispose in the callback (though I haven’t tried this — I guess it is possible that the Timer might be locked during the callback).Edit: No, I guess you can’t do this, since you have to specify the callback parameter in the
Timerconstructor itself.Maybe something like this? (Again, haven’t actually tried it)
…and to start the timer:
The locking should prevent the timer callback from trying to free the timer prior to the
Timerfield having been set.Addendum: As the commenter pointed out, if
action()does something with the UI, then using aSystem.Windows.Forms.Timeris probably a better bet, since it will run the callback on the UI thread. However, if this is not the case, and it’s down toThread.Sleepvs.Threading.Timer,Threading.Timeris the way to go.