Compare Using Thread.Sleep and Timer for Delayed Execution

Compare using Thread.Sleep and Timer for delayed execution

One difference is that System.Threading.Timer dispatches 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, Timer is going to be much more efficient. It also may be more accurate, since Thread.Sleep is 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, Timer is 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 of Thread.Sleep.

As for destroying the Timer, the callback can accept a parameter, so you may be able to pass the Timer itself 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 Timer constructor itself.

Maybe something like this? (Again, haven't actually tried it)

class TimerState
{
public Timer Timer;
}

...and to start the timer:

TimerState state = new TimerState();

lock (state)
{
state.Timer = new Timer((callbackState) => {
action();
lock (callbackState) { callbackState.Timer.Dispose(); }
}, state, millisecond, -1);
}

The locking should prevent the timer callback from trying to free the timer prior to the Timer field having been set.


Addendum: As the commenter pointed out, if action() does something with the UI, then using a System.Windows.Forms.Timer is 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 to Thread.Sleep vs. Threading.Timer, Threading.Timer is the way to go.

Timer & TimerTask versus Thread + sleep in Java

The advantage of TimerTask is that it expresses your intention much better (i.e. code readability), and it already has the cancel() feature implemented.

Note that it can be written in a shorter form as well as your own example:

Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(
new TimerTask() {
public void run() { NewUploadServer.getInstance().checkAndUploadFiles(); }
}, 0, 60 * 1000);

When to use Task.Delay, when to use Thread.Sleep?

Use Thread.Sleep when you want to block the current thread.

Use await Task.Delay when you want a logical delay without blocking the current thread.

Efficiency should not be a paramount concern with these methods. Their primary real-world use is as retry timers for I/O operations, which are on the order of seconds rather than milliseconds.

Task.Delay vs Thread.Sleep for suspending System.Timers.Timer's job

It depends on what your goal is.

Thread.Sleep will block the system thread that is in use. By default System.Timers.Timer uses the system thread-pool, meaning you wouldn't block your main thread, and the use of Thread.Sleep probably will execute concurrently with the rest of your program. If you desire is to use (and therefore block) a specific thread, you will need use the SynchronizingObject property, in coordination with Thread.Sleep.

Task.Delay will provide a logical delay without blocking the current thread. This is the best approach, unless you have a reason to block a specific thread. Keep in mind you'll need to make your event handler asynchronous to use Task.Delay:

 timer.Elapsed += async (sender, args) =>
{
for (int i = 0; i < 15; i++)
{
await Task.Delay(1000);
...
}
}

difference between System.Threading.Timer and Thread.Sleep() in ASP.NET c#

Thread.Sleep() has some uses for which it is vital. These are few and far between, and if you're using any number higher than about 1 as the argument you almost certainly don't have one.

If it's even possible for a timer to be used instead, then you definitely don't have one. Don't block a perfectly good thread when the alternative isn't even difficult.

Do be careful of the case where a timer is triggered while the previous trigger is still running. Depending on the nature of the operation you will want to either:

  1. Ignore this, if the code called is safe for multiple simultaneous calls then this may be fine. Of course, you have to know that it's fine.
  2. Lock on the timer-triggered operation. Be aware that you can end up with a queue of lots of pending operations.
  3. Lock on the timer-triggered operation, try to obtain the lock with a timeout of zero and if you fail then skip it - there's a thread still here from the last time.
  4. Have the timer as a one-off timer that you restart at the end of each call.

Difference between Task.Delay() and new Task(()= Thread.Sleep())

Task.Delay isn't same as staring a Task with Thread.Sleep. Task.Delay uses Timer internally and thus it doesn't blocks any thread, however starting a new Task with Thread.Sleep blocks the thread (typically Threadpool thread).

In your example you never started the Task. Creating a Task with constructor will return a Unstarted task needs to be started with a call to Start method. Otherwise it will never complete(because you never started it).

However calling Task.Start is discouraged, You can call Task.Factory.StartNew(()=> Thread.Sleep(1000)) or Task.Run(()=> Thread.Sleep(1000)) if you want to waste a resource.

Also, be aware that StartNew is dangerous, you should prefer Task.Run over StartNew unless there's a compelling reason to do so.

Thread.Sleep vs Task.Delay?

The documentation on MSDN is disappointing, but decompiling Task.Delay using Reflector gives more information:

public static Task Delay(int millisecondsDelay, CancellationToken cancellationToken)
{
if (millisecondsDelay < -1)
{
throw new ArgumentOutOfRangeException("millisecondsDelay", Environment.GetResourceString("Task_Delay_InvalidMillisecondsDelay"));
}
if (cancellationToken.IsCancellationRequested)
{
return FromCancellation(cancellationToken);
}
if (millisecondsDelay == 0)
{
return CompletedTask;
}
DelayPromise state = new DelayPromise(cancellationToken);
if (cancellationToken.CanBeCanceled)
{
state.Registration = cancellationToken.InternalRegisterWithoutEC(delegate (object state) {
((DelayPromise) state).Complete();
}, state);
}
if (millisecondsDelay != -1)
{
state.Timer = new Timer(delegate (object state) {
((DelayPromise) state).Complete();
}, state, millisecondsDelay, -1);
state.Timer.KeepRootedWhileScheduled();
}
return state;
}

Basically, this method is just a timer wrapped inside of a task. So yes, you can say it's just like timer.



Related Topics



Leave a reply



Submit