HOWTO · Csharp

How to Make a Delay Timer in C#

This article introduces how to make a delay timer in C#. It includes four different methods: Thread.Sleep(), Task.Delay(), System.Timers.Timer, and System.Threading.Timer.

On this page

To add a delay in C#, choose Thread.Sleep() to block the current thread, Task.Delay() to wait asynchronously, or a timer class to schedule a callback. The examples below use a two-second interval and show how each option behaves. They have not been executed in the supplied runtime, so no observed output is claimed.

Use the Thread.Sleep() Method to Make a Delay in C#

Thread.Sleep() pauses the current thread for the specified number of milliseconds. Because that thread cannot do other work during the wait, use this approach only when blocking is appropriate, such as in a short synchronous console program.

This complete example prints a message, waits for two seconds, and then prints another message:

using System;
using System.Threading;

class DelayExample
{
    static void Main()
    {
        Console.WriteLine("The delay starts.");
        Thread.Sleep(2000);
        Console.WriteLine("The delay ends.");
    }
}

The argument is milliseconds, so 2000 requests a two-second wait. The actual elapsed time can vary with system scheduling.

Use the Task.Delay() Method to Make a Delay in C#

Task.Delay() creates a task that completes after the requested interval. Awaiting it in an asynchronous method lets that method yield while waiting, unlike Thread.Sleep(), which occupies the current thread. Call the asynchronous method from your application’s existing async flow.

This complete example keeps the asynchronous wait in a separate method and uses a synchronous entry point to call it:

using System;
using System.Threading.Tasks;

class DelayExample
{
    static void Main()
    {
        RunAsync().GetAwaiter().GetResult();
    }

    static async Task RunAsync()
    {
        Console.WriteLine("Before the delay");
        await Task.Delay(2000);
        Console.WriteLine("After the delay");
    }
}

The await expression resumes RunAsync after the delay task completes. In an application that already uses async methods, await Task.Delay(2000) directly instead of blocking the entry point to wait for the task.

Use the System.Timers.Timer Class to Make a Delay in C#

System.Timers.Timer raises an Elapsed event after its Interval in milliseconds. Set AutoReset to false for a single event; set it to true when the event should repeat at the interval. The callback is event-driven, so starting a timer does not pause the next line of code.

This complete example waits for the one-shot event before the console program exits:

using System;
using System.Threading;
using System.Timers;

class DelayExample
{
    static void Main()
    {
        using (var completed = new ManualResetEvent(false))
        using (var timer = new System.Timers.Timer(2000))
        {
            timer.AutoReset = false;
            timer.Elapsed += (sender, args) =>
            {
                Console.WriteLine("Timer elapsed.");
                completed.Set();
            };

            Console.WriteLine("Timer started.");
            timer.Start();
            completed.WaitOne();
        }
    }
}

WaitOne() keeps this console example alive until the event handler signals completion. In a longer-running application, keep the application alive according to its normal event loop or service lifetime instead of adding a blocking wait solely for the timer.

Use the System.Threading.Timer Class to Make a Delay in C#

System.Threading.Timer schedules a callback with an initial due time and a period. Both values are in milliseconds. Use Timeout.Infinite for the period when the callback should run once; provide a finite period to schedule repeated callbacks. The callback runs separately from the code that starts the timer.

This complete example schedules one callback after two seconds and waits for it before exiting:

using System;
using System.Threading;

class DelayExample
{
    static void Main()
    {
        using (var completed = new ManualResetEvent(false))
        using (var timer = new System.Threading.Timer(
            state =>
            {
                Console.WriteLine("Timer callback.");
                completed.Set();
            },
            null,
            2000,
            Timeout.Infinite))
        {
            Console.WriteLine("Timer scheduled.");
            completed.WaitOne();
        }
    }
}

The due time schedules the first callback two seconds after construction. Timeout.Infinite prevents another callback from being scheduled. The wait keeps this console example alive long enough to receive the callback; an application with its own event loop can use that lifetime instead.

Conclusion

Use Thread.Sleep() for a simple synchronous pause when blocking the current thread is acceptable. Prefer Task.Delay() with await in asynchronous code so the method can yield while it waits. Choose System.Timers.Timer or System.Threading.Timer when you need callback-based scheduling, with AutoReset or the timer period controlling repetition. Timer callbacks schedule work; they do not pause sequential execution, and their timing is not an exact wall-clock guarantee.