How to put a task to sleep (or delay) in C# 4.0?
You can use a Timer
to create a Delay
method in 4.0:
public static Task Delay(double milliseconds)
{
var tcs = new TaskCompletionSource<bool>();
System.Timers.Timer timer = new System.Timers.Timer();
timer.Elapsed+=(obj, args) =>
{
tcs.TrySetResult(true);
};
timer.Interval = milliseconds;
timer.AutoReset = false;
timer.Start();
return tcs.Task;
}
Tasks on Framework 4.0: Put a timeout on the innermost task in a chain of continuations
You can try to create task with CancellationToken
and then call tokenSource.CancelAfter(...)
like this
var tokeSource = new CancellationTokenSource();
Task.Run(() => { Console.WriteLine("processing"); }, tokenSource.Token);
tokenSource.CancelAfter(TimeSpan.FromSeconds(30));
In .Net 4.0 you can implement CancelAfter
by yourself with something like
public static class CancellationTokenSourceExtensions
{
public static Task CancelAfter(this CancellationTokenSource cts, TimeSpan timeout)
{
return Task.Delay(timeout).ContinueWith(t => cts.Cancel());
}
}
I personally think that cts
-based solution is more with the spirit of TPL.
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.
Diference between task.wait , Task.delay and thread.sleep
Basically Wait()
and Sleep()
are both thread blocking operations,in other words they force a thread to sit idle instead of doing work elsewhere. Delay
on other hand uses a timer internally that releases the thread in use until the delay is complete.
There is much more that can be said about these three functions so here's a small sample set for further reading.
More Info
- There is no thread
- Don't Block on Async Code
- When to use Task.Delay, when to use Thread.Sleep?
- Thread.Sleep vs Task.Delay?
- Thread.Sleep is a sign of a poorly designed program.
public class WaitSleepDelay
{
/// <summary>
/// The thread is released and is alerted when the delay finishes
/// </summary>
/// <returns></returns>
public async Task Delay()
{
//This Code Executes
await Task.Delay(1000);
//Now this code runs after 1000ms
}
/// <summary>
/// This blocks the currently executing thread for the duration of the delay.
/// This means that the thread is held hostage doing nothing
/// instead of being released to do more work.
/// </summary>
public void Sleep()
{
//This Code Executes
Thread.Sleep(1000);
//Now this code runs after 1000ms
}
/// <summary>
/// This blocks the currently executing thread for the duration of the delay
/// and will deadlock in single threaded sync context e.g. WPF, WinForms etc.
/// </summary>
public void Wait()
{
//This Code Executes
Task.Delay(1000).Wait();
//This code may never execute during a deadlock
}
}
Call Thread.Sleep from the Task
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.
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.
Is Task.Delay undocumented in .NET 4?
This method does not exist in .NET 4.0.
You are probably ILspying 4.5. All of .NET 4.x's assemblies, through 4.5.2 at the time of this post, show v4.0.0.0, and newer versions replace older versions when you install them -- they're made to be backward compatible.
When you are able to grab Task.Delay
through reflection, it's because your app is actually running on .NET 4.5.
When you select a framework version in Visual Studio, it will use whatever version you have installed, but only show the methods actually in that selection -- you can think of it as a compatibility selection, not so much an exact version selection.
I believe one of the Microsoft.Bcl and Microsoft.Bcl.Async packages on NuGet contains a TaskEx.Delay
you can use which will emulate it on older frameworks and route to the build-in version when used on newer ones. These packages contain back-ported APIs.
Related Topics
Grid Lines Are Not Displaying in Grid View
Add CSS Class to a Div in Code Behind
Applying CSS on ASP.NET Fileupload Control's Browse Button Only
ASP.NET Page Is Not Loading CSS Styles
Signalr(V2.2.0) Ondisconnected Set User Offline
Arkit Body Tracking Using Xamarin and C# Inaccurate
Does C# Have an Equivalent to JavaScript's Encodeuricomponent()
Understanding Floating Point Problems
How to Flatten an Expandoobject Returned via JSONresult in ASP.NET MVC
Using C# to Dynamically Generate CSS Files
Send Push to Android by C# Using Fcm (Firebase Cloud Messaging)
Adding Distance to a Gps Coordinate
How to Manage Files on an Mtp Portable Device
Xamarin iOS Memory Leaks Everywhere
Difference Between Casting and Using the Convert.To() Method