Contents
Introduction
When programming, it is common to want to pause execution for a certain amount of time and most common programming and scripting languages have some form of Sleep command built in to achieve this.
For example, when weāve encountered a problem with a remote resource, itās common to back-off (pause execution) for a short amount of time and retry.
Here Iāll go through the various options for introducing a delay in C#, ranging from the most basic (Thread.Sleep()) ā suitable for use in a single threaded console application. To more complicated versions for use in multi threaded interactive applications.
Add a delay in C# using Thread.Sleep()
// Will delay for three seconds Thread.Sleep(3000);
Using Thread.Sleep() is the simplest way to introduce a delay in C# code, but it will hang the main thread for the duration of the delay, so itās only really appropriate for console applications. Assuming youāre happy with that, letās dive into a more complete example:
using System; using System.Threading; class Program { static void Main() { Console.WriteLine($"Delay starting at {DateTime.Now}"); // Will delay for three seconds var milliseconds = 3000; Thread.Sleep(milliseconds); Console.WriteLine($"Finished delay at {DateTime.Now}"); } } /* this code outputs: Delay starting at 13/11/2020 11:59:39 Finished delay at 13/11/2020 11:59:42 */
A common mistake when first using Thread.Sleep() is to forget the using, result in the following error:
error CS0103 C# The name 'Thread' does not exist in the current context
This is easily fixed by adding a āusing System.Threading;ā line at the top of the file, as in the above example.
The next thing to note is that Thread.Sleep() takes miliseconds as itās argument, so if you want to sleep for 3 seconds you need to pass the number 3000. Itās possible to make your intent clearer using a timespan like this:
Thread.Sleep(TimeSpan.FromSeconds(3));
But older versions of Thread.Sleep didnāt take a TimeSpan, so your mileage may vary.
Add a Delay in C# without blocking main thread using Task.Delay()
// Will delay for 3 seconds await Task.Delay(3000);
There is an asynchronous version of Thread.Sleep called Task.Delay. If youāre not familiar with how asynchronous calls work in C# then Iām planning a series of posts on the topic (let me know you want it in the comments!). Until thatās up, see the official docs if you need more info.
The idea here is to start a new task that runs the delay in the background, letās look at an example:
using System; using System.Threading.Tasks; class Program { async static Task Main() { Console.WriteLine($"Delay starting at {DateTime.Now}"); // Will delay for 3 seconds await Task.Delay(3000); Console.WriteLine($"Finished delay at {DateTime.Now}"); } } /* this code outputs: Delay starting at 13/11/2020 12:23:09 Finished delay at 13/11/2020 12:23:12 */
Once again if you forget the using, you might encounter the following error:
CS0246 C# The type or namespace name 'Task' could not be found (are you missing a using directive or an assembly reference?)
Be sure to add āusing System.Threading.Tasks;ā to avoid this.
Note also that weāve had to make our main method async and return a Task rather than void. This is a contrived example, and if youāve got a console application as simple of this one thereās no need for this asynchronous version (just use sleep). Forgetting to do that can result in this error:
CS4033 C# The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'.
So what can we do with this asynchronous delay that canāt be done with the basic Thread.Sleep()? Quite simply, we can get other things done while we wait for the delay to finish. Time for a further example:
using System; using System.Threading; using System.Threading.Tasks; class Program { static void Main() { Console.WriteLine($"Delay starting at {DateTime.Now}"); //Sleep for 3 seconds in the background var delay = Task.Delay(TimeSpan.FromSeconds(3)); var seconds = 0; while (!delay.IsCompleted) { // While we're waiting, note the time ticking past seconds++; Thread.Sleep(TimeSpan.FromSeconds(1)); Console.WriteLine($"Waiting... {seconds}"); } Console.WriteLine($"Finished delay at {DateTime.Now} after {seconds} seconds"); } } /* this code outputs: Delay starting at 13/11/2020 12:44:49 Waiting... 1 Waiting... 2 Waiting... 3 Finished delay at 13/11/2020 12:44:52 after 3 seconds */
This example makes use of the fact that Task.Delay() is running in the background, and allows the main thread to do some useful (or not!) work. In this example the main thread just outputs āWaitingā¦ {seconds}ā, but Iād argue that even that is useful as it provides feedback to the user that the console application is still actively working, it could easily be updated to print the % done or similar.
I hope Iāve not confused things by combining both Task.Delay() and Thread.Sleep() in one example!
For interactive (non-console) applications itās especially important that the main thread can respond to inputs, allowing the program to remain interactive while delays are processed in the background.
Add a repeating delay in C# using one of the Timer classes
There are several timer classes that can be used to repeatedly trigger events after a certain period of time has elapsed:
System.Timers.Timer
System.Threading.Timer
System.Windows.Forms.TimerĀ (.NET Framework only)
System.Web.UI.Timer
System.Windows.Threading.DispatcherTimer
Each of these timer classes has different functionality, with these remarks on MSDN giving more details of which to use depending on your requirements.
If you just want a single delay in C# then use either Thread.Sleep() or Task.Delay() as described above. However, if youāre after a repeating delay, a timer can be helpful.
For the purposes of the following examples, Iām going to use a System.Threading.Timer() as it appears to be Microsoft preferred general purpose timer.
The thrust of using a timer comes from instantiating a new System.Threading.Timer(), to which you need to supply at least three arguments: callback, dueTime and period.
- callback TimerCallback ā this is the method that should be called whenever the timer fires
- dueTime int/Timespan ā this is how long to wait before the timer first fires
- period int/TimeSpan ā this is how long to wait between each subsequent firing of the timer
As example of such an instantiation might be:
var timer = new System.Threading.Timer( DoSomething, null, TimeSpan.FromSeconds(5), // time to first firing TimeSpan.FromSeconds(1)); // delay for each subsequent firing
This starts a timer that will wait 5 seconds before calling DoSomething, which it will continue to do once a second after that.
The following example is more complete, showing you how to set up the callback, one way of tracking the number of times itās called, and how to signal that the timer should finish and then stop it. Hereāre the code:
using System; using System.Threading; class Program { static void Main() { Console.WriteLine($"Delay starting at {DateTime.Now}"); var idleWaiter = new IdleWaiter(3); // Create an AutoResetEvent to signal when the IdleWaiter was reached it's limit var autoEvent = new AutoResetEvent(false); var timer = new System.Threading.Timer( idleWaiter.PrintWaiting, autoEvent, TimeSpan.FromSeconds(1), // time to first firing TimeSpan.FromSeconds(1)); // delay for each subsequent firing // Wait until the autoevent signals; autoEvent.WaitOne(); // Dispose of the timer timer.Dispose(); Console.WriteLine($"Finished delay at {DateTime.Now} after {idleWaiter.TimesCalled} seconds"); } } class IdleWaiter { public IdleWaiter(int threshold) { this.Threshold = threshold; } public int TimesCalled { get; private set; } public int Threshold { get; } public void PrintWaiting(object stateInfo) { var autoEvent = (AutoResetEvent)stateInfo; Console.WriteLine($"Waiting... {++this.TimesCalled}"); if (this.TimesCalled >= Threshold) { autoEvent.Set(); } } } /* this code outputs: Delay starting at 13/11/2020 13:44:39 Waiting... 1 Waiting... 2 Waiting... 3 Finished delay at 13/11/2020 13:44:42 after 3 seconds */
I know itās a bit heavy, but in the above example Iāve created a new class IdleWaiter which is responsible for printing āWaitingā¦ā each time itās called, while tracking the number of times itās been called and signalling (via an autoResetEvent) when itās reached a threshold.
When you run this code, the timer fires every seconds until itās been run three times, then it signals that itās reached itās threshold and we stop the timer by disposing of it.
If we didnāt dispose of the timer it would keep on ticking once every second. You can try this for yourself by commenting out the dispose line and adding a Thread.Sleep() to stop the program exiting:
// Dispose of the timer //timer.Dispose(); Console.WriteLine($"Finished delay at {DateTime.Now} after {idleWaiter.TimesCalled} seconds"); Thread.Sleep(5000);
If you run the above code with this change you get the following output:
Delay starting at 13/11/2020 13:56:32 Waiting... 1 Waiting... 2 Waiting... 3 Finished delay at 13/11/2020 13:56:35 after 3 seconds Waiting... 4 Waiting... 5 Waiting... 6 Waiting... 7 Waiting... 8
Using a Timer might be the right choice if you want a task to repeat on a schedule, but given the added complexity, Iād probably stick to the other options for most use cases.
Conclusion
If youāre in a console app, or some other single threaded application, you can use Thread.Sleep() to trigger a delay, just be careful with the fact this takes milliseconds (or better yet use TimeSpan.FromSeconds()).
If you want to delay in an asynchronous way, allowing your main thread to do useful work in the interim, Thread.Delay() is they way to go.
If youāre want to kick something off repeatedly with a delay in between, then you should be using a timer like System.threading.Timer.
Iām sure there are other ways of adding a delay in C#, but I think Iāve covered off the most important ones. If thereās something you think Iāve missed that deserved to be included, if you think Iāve got something wrong, or if you just want to congratulate me on a job well done then please let me know in the comments.
Mean while, if you want to go deep on another area of C#, might I recommend my recent post on using (or abusing?) Linq style foreach.
Very Nice Explanation with Examplesā¦
Good Jobā¦.
Thanks! š
so there is no shame in using thread.sleep in a console app then, great! thanks. I keep reading that with the thread timer it can get garbage collected and stop and I have seen in a small app that I am writing now when left to run for 24 hours checking a directory for a file that the app has stopped for some reason so it makes me nervous to use a timer Great blog .