Is it correct to use Thread.Sleep() inside the task. Or is only a timer (Task.Delay() in .Net 4.5 and latter) used with task? Or maybe another approaches exist.
-
1The question is what do you want to achieve? As there are pros and cons to all approaches. – Matt Wilko Dec 16 '13 at 12:15
-
1You can but it's a very bad practice because you are disabling a ThreadPool thread that could be used to server other tashs. What are you trying to achieve? – Panagiotis Kanavos Dec 16 '13 at 12:22
-
@MattWilko I think SerG is looking for an alternative to Task.Delay() for .NET 4.0 as that was introduced in .NET 4.5. – Theraot Dec 16 '13 at 12:22
-
If you're looking for Task.Delay in [.Net4.0](http://stackoverflow.com/a/15342256/2530848) – Sriram Sakthivel Dec 16 '13 at 12:26
-
Serg, is it for .NET 4.0? also do you want a `CancellationToken`? – Theraot Dec 16 '13 at 12:30
-
It's for .NET 4.0, but question is about right way to pause a task. – SerG Dec 16 '13 at 13:47
3 Answers
You can use Thread.Sleep
inside a task.
But in most situations I'd prefer to use await Task.Delay
which does not block the thread.
If you're using Task.Run
(which uses a ThreadPool thread), then you should try not to block the thread. As it is a shared thread, there may be other code waiting to run.
I would still use Thread.Sleep(0)
when I'm done using the thread, to yield the processor and give up your time slice.

- 66,540
- 21
- 145
- 155
-
3Indeed, you *can* use it, but as far as the OP goes I would say it is definitely "not correct" to sleep a task pool thread when it could be handling other work! – Dan Puzey Dec 16 '13 at 12:18
-
dcastro, are you sure that Sleep(0) is not removed during the optimization by a compiler as meaningless redundant statement? I haven't found any information in msdn about such trick. – SerG Dec 16 '13 at 14:18
-
1@SerG From [here](http://msdn.microsoft.com/en-us/library/d00bd51t(v=vs.110).aspx): "Specify zero (0) to indicate that this thread should be suspended to allow other waiting threads to execute." – dcastro Dec 16 '13 at 14:20
It seems the real question is how to achieve the same effect as .NET 4.5's Task.Delay
in .NET 4.0.
First, if you use Visual Studio 2012+ you can add the Microsoft.Bcl.Async nuget package to your project to enable async/await
and other new functionality like Task.Delay. This is the most convenient method.
If you are using Visual Studio 2010, you can achieve the same results by creating a TaskCompletionSource that completes when a timer expires. This is already provided by the ParallelExtensionsExtras library as a set of extension methods.
The basic function is StartNewDelayed
and there are many convenience overloads:
/// <summary>Creates a Task that will complete after the specified delay.</summary>
/// <param name="factory">The TaskFactory.</param>
/// <param name="millisecondsDelay">The delay after which the Task should transition to RanToCompletion.</param>
/// <param name="cancellationToken">The cancellation token that can be used to cancel the timed task.</param>
/// <returns>A Task that will be completed after the specified duration and that's cancelable with the specified token.</returns>
public static Task StartNewDelayed(this TaskFactory factory, int millisecondsDelay, CancellationToken cancellationToken)
{
// Validate arguments
if (factory == null) throw new ArgumentNullException("factory");
if (millisecondsDelay < 0) throw new ArgumentOutOfRangeException("millisecondsDelay");
// Check for a pre-canceled token
if (cancellationToken.IsCancellationRequested)
return factory.FromCancellation(cancellationToken);
// Create the timed task
var tcs = new TaskCompletionSource<object>(factory.CreationOptions);
var ctr = default(CancellationTokenRegistration);
// Create the timer but don't start it yet. If we start it now,
// it might fire before ctr has been set to the right registration.
var timer = new Timer(self =>
{
// Clean up both the cancellation token and the timer, and try to transition to completed
try
{
ctr.Dispose();
}
catch (NullReferenceException)
{
// Eat this. Mono throws a NullReferenceException when constructed with
// default(CancellationTokenRegistration);
}
((Timer)self).Dispose();
tcs.TrySetResult(null);
});
// Register with the cancellation token.
if (cancellationToken.CanBeCanceled)
{
// When cancellation occurs, cancel the timer and try to transition to canceled.
// There could be a race, but it's benign.
ctr = cancellationToken.Register(() =>
{
timer.Dispose();
tcs.TrySetCanceled();
});
}
// Start the timer and hand back the task...
try { timer.Change(millisecondsDelay, Timeout.Infinite); }
catch(ObjectDisposedException) {} // in case there's a race with cancellation; this is benign
return tcs.Task;
}
Most of the code deals with properly disposing of the timer and handling cancellations.

- 120,703
- 13
- 188
- 236
In .NET 4.5 you should use Task.Delay
. In .NET 4.0, since it doesn't have Task.Delay
and Thread.Sleep
inside a Task is a bad practice... create a custom task, and use a timer to mark ti as completed.

- 31,890
- 5
- 57
- 86