Compare using Thread.Sleep and Timer for deferred execution

I have a method that should be delayed for a specified 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 read several articles about using Thread.Sleep - poor design. But I do not quite understand why.

But to use Timer, Timer has a dispose method. Since execution is delayed, I don’t know how to manage the timer. Do you have any suggestions?

Or, if you have alternative codes for deferred execution, we will also be grateful.

+55
multithreading c # sleep timer delayed-execution
Dec 24 '08 at 15:04
source share
6 answers

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.

+42
Dec 24 '08 at 16:09
source share

use ThreadPool.RegisterWaitForSingleObject instead of a timer:

 //Wait 5 seconds then print out to console. //You can replace AutoResetEvent with a Semaphore or EventWaitHandle if you want to execute the command on those events and/or the timeout System.Threading.ThreadPool.RegisterWaitForSingleObject(new AutoResetEvent(false), (state, bTimeout) => Console.WriteLine(state), "This is my state variable", TimeSpan.FromSeconds(5), true); 
+16
Jul 30 '09 at 23:51
source share

I think Thread.Sleep is fine if you really want to pause the application for a certain amount of time. I think the reason people say that this is a bad design is because in most situations, people actually don't want the application to pause.

For example, I worked on the pop3 client, where the programmer used Thread.Sleep (1000) to wait for the socket to receive mail. In this situation, it was better to connect the event handler to the socket and continue executing the program after the socket terminated.

+14
Dec 24 '08 at 15:16
source share

I remember implementing a solution like Eric one. This, however, is a worker;)

 class OneTimer { // Created by Roy Feintuch 2009 // Basically we wrap a timer object in order to send itself as a context in order to dispose it after the cb invocation finished. This solves the problem of timer being GCed because going out of context public static void DoOneTime(ThreadStart cb, TimeSpan dueTime) { var td = new TimerDisposer(); var timer = new Timer(myTdToKill => { try { cb(); } catch (Exception ex) { Trace.WriteLine(string.Format("[DoOneTime] Error occured while invoking delegate. {0}", ex), "[OneTimer]"); } finally { ((TimerDisposer)myTdToKill).InternalTimer.Dispose(); } }, td, dueTime, TimeSpan.FromMilliseconds(-1)); td.InternalTimer = timer; } } class TimerDisposer { public Timer InternalTimer { get; set; } } 
+2
Jul 22 '10 at 6:41
source share

The only beef I have in System.Timer is that most of the time I saw that it was used for long delays (hours, minutes) in polling services, and developers often forget to fire an event. Before starting the timer. This means that if I run an application or service, I need to wait until the timer expires (hours, minutes) before it starts running.

Of course, this is not a problem with the timer, but I think that it is often used incorrectly, because it is too easy to abuse.

+1
Dec 24 '08 at 17:09
source share

@miniscalope No, do not use ThreadPool.RegisterWaitForSingleObject instead of a timer, System.Threading.Timer will put a callback queue that will be executed on the thread pool thread when the time is up and does not require a wait descriptor, wait for a single object to bind the thread thread waiting for when the event will be signaled, or it will time out before the thread calls the callback.

0
Jul 31 '09 at 1:30
source share



All Articles