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 .