If you are learning C# or building a .NET application, you will eventually need code that runs later, repeats every few seconds, checks a service, updates a UI, or schedules background work. That is where timers come in. Understanding how to use a timer in C# helps you build periodic tasks, delayed actions, polling loops, UI updates, and backend maintenance jobs without blocking the main thread.
The confusing part is that C# and .NET have several timer options. A console application timer may use System.Threading.Timer, a service might use System.Timers.Timer, a Windows Forms app usually needs System.Windows.Forms.Timer, and modern async code may work better with PeriodicTimer or Task.Delay.
This guide explains the main timer types in C#, when to use each one, and how to write practical examples. You will see beginner-friendly code for interval-based execution, one-time delayed execution, timer callback functions, async timer patterns, and Windows Forms timers. You can follow along in Visual Studio, JetBrains Rider, the dotnet CLI, or a C# Interactive REPL.
For related fundamentals, see /csharp-basics, /dotnet-tutorials, and /async-programming-guide.
Direct Answer Box:
You use a timer in C# by choosing the right timer type, setting an interval or delay, and attaching a callback method or event handler that runs when the timer fires. For backend or console apps, use System.Threading.Timer, System.Timers.Timer, or PeriodicTimer; for Windows Forms, use System.Windows.Forms.Timer; for simple async delays, use Task.Delay.
A timer lets your program run code after time passes. That may mean “run this once after 5 seconds” or “run this every 10 seconds until the app stops.” In C#, this is useful for polling APIs, refreshing dashboards, cleaning temporary files, checking job status, saving drafts, or updating a clock on a form.
Timer Type (System.Timers / System.Threading / Windows Forms Timer) + Interval + Callback Method = Scheduled Execution in C#
The timer type controls where and how the code runs. The interval controls when it runs. The callback method contains the work.
Microsoft’s .NET documentation explains that .NET provides multiple timer classes for different environments. System.Threading.Timer executes a callback on a ThreadPool thread. System.Timers.Timer raises an elapsed event, usually on a ThreadPool thread. System.Threading.PeriodicTimer supports async waiting for individual ticks. Windows desktop apps may also use System.Windows.Forms.Timer, which runs on the UI thread.
That distinction matters. A timer that works well in a backend service may be wrong for a Windows Forms app. A UI timer should update controls safely on the UI thread. A backend timer should avoid blocking and handle overlapping executions carefully.
How to Use a Timer in C# Step by Step
Step 1: Choose the Right Timer Type
Use this quick guide:
Timer TypeBest ForRuns OnSystem.Timers.TimerService-style recurring eventsUsually ThreadPoolSystem.Threading.TimerLightweight callback-based background workThreadPoolSystem.Threading.PeriodicTimerModern async periodic loopsAsync flowSystem.Windows.Forms.TimerWindows Forms UI updatesUI threadTask.DelaySimple one-time delay or async loopAsync flow
If you are writing a backend worker, console app, or service, start with PeriodicTimer for async code or System.Threading.Timer for callback-based code. If you are building a form with buttons and labels, use System.Windows.Forms.Timer.
Step 2: Set the Interval
Most timer APIs use milliseconds or TimeSpan. Use TimeSpan when possible because it is easier to read and less error-prone.
// 5 seconds as milliseconds
int interval = 5000;
// 5 seconds as TimeSpan
TimeSpan intervalTime = TimeSpan.FromSeconds(5);
Step 3: Write the Callback or Handler
The callback is the method that runs when the timer fires.
static void DoWork()
{
Console.WriteLine($”Timer fired at {DateTime.Now:T}”);
}
Step 4: Start and Stop the Timer
Timers often keep running until you stop or dispose them. Always clean them up when your program no longer needs them.
timer.Dispose();
C# Timer Examples for Common Scenarios
System.Timers in C#: Event-Based Periodic Task
System.Timers.Timer is beginner-friendly because it uses an Elapsed event. It is common in service-style applications and simple periodic tasks.
using System;
using System.Timers;
class Program
{
private static Timer? _timer;
static void Main()
{
_timer = new Timer(2000); // 2 seconds
_timer.Elapsed += OnTimerElapsed;
_timer.AutoReset = true;
_timer.Enabled = true;
Console.WriteLine(“Timer started. Press Enter to stop.”);
Console.ReadLine();
_timer.Stop();
_timer.Dispose();
}
private static void OnTimerElapsed(object? sender, ElapsedEventArgs e)
{
Console.WriteLine($”System.Timers.Timer fired at {e.SignalTime:T}”);
}
}
System.Threading.Timer Usage: Callback-Based Timer
System.Threading.Timer is lightweight and uses a timer callback function in C#. It is useful when you want a direct callback instead of an event.
using System;
using System.Threading;
class Program
{
private static Timer? _timer;
static void Main()
{
_timer = new Timer(
callback: CheckStatus,
state: null,
dueTime: TimeSpan.FromSeconds(1),
period: TimeSpan.FromSeconds(3));
Console.WriteLine(“Threading timer running. Press Enter to exit.”);
Console.ReadLine();
_timer.Dispose();
}
private static void CheckStatus(object? state)
{
Console.WriteLine($”Checking status at {DateTime.Now:T}”);
}
}
C# Delay Execution with Task.Delay
For one-time delay execution, a full timer may be unnecessary. Task.Delay is often the cleanest option.
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
Console.WriteLine(“Waiting 3 seconds…”);
await Task.Delay(TimeSpan.FromSeconds(3));
Console.WriteLine(“This runs after the delay.”);
}
}
Async Timer C# Example with PeriodicTimer
For modern async code, PeriodicTimer is often the cleanest option because it works naturally with await.
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
using var timer = new PeriodicTimer(TimeSpan.FromSeconds(2));
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
try
{
while (await timer.WaitForNextTickAsync(cts.Token))
{
Console.WriteLine($”Async tick at {DateTime.Now:T}”);
}
}
catch (OperationCanceledException)
{
Console.WriteLine(“Timer cancelled.”);
}
}
}
Windows Forms Timer C# Example
A Windows Forms timer is designed for UI apps. It runs on the UI thread, so it can safely update controls like labels.
using System;
using System.Windows.Forms;
public partial class MainForm : Form
{
private readonly Timer _timer = new Timer();
public MainForm()
{
InitializeComponent();
_timer.Interval = 1000; // 1 second
_timer.Tick += Timer_Tick;
_timer.Start();
}
private void Timer_Tick(object? sender, EventArgs e)
{
timeLabel.Text = DateTime.Now.ToLongTimeString();
}
}
Choosing the Best Timer for Scheduling Tasks in C#
Use the right timer for the application type. That decision prevents many subtle bugs.
Use System.Timers.Timer when you want an event-based timer for service-style recurring execution.
Use System.Threading.Timer when you want a lightweight callback function and can safely handle shared state.
Use PeriodicTimer when you are writing async code with cancellation support.
Use System.Windows.Forms.Timer when you are building Windows Forms UI updates.
Use Task.Delay when you only need a simple delay and do not need a long-lived timer object.
A useful benchmark from Microsoft’s timer documentation: Windows Forms Timer is single-threaded and limited to about 55 milliseconds of accuracy, while System.Threading.Timer and System.Timers.Timer use system clock resolution. In practice, timers are not precision schedulers. They are good for application-level intervals, not hard real-time execution.
Common Mistakes When Using Timers in C#
One common mistake is letting the timer be garbage collected. If you create a System.Threading.Timer inside a method and do not keep a reference to it, the runtime may collect it. Store it in a field when it needs to stay active.
Another mistake is assuming timer callbacks never overlap. If the callback takes longer than the interval, another callback may begin before the first one finishes. This can cause duplicate work, race conditions, and corrupted shared state.
private static int _isRunning = 0;
private static void DoWork(object? state)
{
if (Interlocked.Exchange(ref _isRunning, 1) == 1)
return;
try
{
Console.WriteLine(“Running scheduled work…”);
Thread.Sleep(5000);
}
finally
{
Interlocked.Exchange(ref _isRunning, 0);
}
}
Do not block UI timers with long-running work. A Windows Forms timer runs on the UI thread, so slow code can freeze the interface. Move heavy work to a background task and update the UI when complete.
Do not use timers as a replacement for durable job scheduling. For serious scheduling tasks in C#, especially jobs that must survive app restarts, use a scheduler, hosted service, queue, database-backed job system, or cloud scheduler.
Finally, always handle exceptions. Timer exceptions can behave differently depending on the timer type and whether async code is involved. Log failures and design your callback so one bad run does not silently break the application.
The TIMER Framework for C# Timer Decisions
Use the TIMER Framework to choose and implement timers correctly:
T: Types
Choose the timer based on the application: console/backend, Windows Forms, or simple async delay.
I: Implementation
Create the timer, set its interval, and connect the callback or event handler.
M: Methods
Decide whether the work should run once, repeatedly, or until cancellation.
E: Execution
Know where the code runs. ThreadPool timers are not UI-safe. UI timers are not good for heavy work.
R: Runtime Behavior
Think about drift, overlap, disposal, app shutdown, and error handling.
Use this checklist before shipping:
Did you choose the right timer type?
Is the interval readable and intentional?
Can the callback overlap?
Are exceptions logged?
Is the timer disposed?
Does UI code run on the UI thread?
Should this be a real scheduler instead?
Conclusion
Learning how to use a timer in C# is really about choosing the right timing tool for the job. Use Task.Delay for simple delayed execution, System.Timers.Timer for event-based periodic tasks, System.Threading.Timer for lightweight callback-based work, PeriodicTimer for modern async loops, and System.Windows.Forms.Timer for Windows Forms UI updates.
The safest pattern is to start small: create a console application timer, log a message every few seconds, add cancellation, then test what happens when the callback takes longer than the interval. That small project will teach you more than memorizing timer classes.
Next step: build a mini timer-based project, such as a console heartbeat logger, a simple reminder app, or a background health-check worker using the .NET SDK, Visual Studio, or the dotnet CLI.
What is the best timer to use in C#?
The best timer depends on the application. Use PeriodicTimer for modern async code, System.Threading.Timer for lightweight callbacks, System.Timers.Timer for event-based server tasks, and System.Windows.Forms.Timer for Windows Forms UI updates. There is no single best timer for every project.
How do I run code every 5 seconds in C#?
Create a timer with a 5-second interval and place your logic in the callback or event handler. In modern async code, PeriodicTimer with TimeSpan.FromSeconds(5) is clean and readable. For callback-based code, System.Threading.Timer also works well.
How do I delay execution in C#?
Use await Task.Delay(TimeSpan.FromSeconds(3)) when you simply want to wait before continuing. This is usually better than creating a timer for one delayed action. In synchronous code, avoid blocking with Thread.Sleep unless you intentionally want to block the current thread.
What is the difference between System.Timers.Timer and System.Threading.Timer?
System.Timers.Timer raises an Elapsed event, while System.Threading.Timer executes a callback delegate. Both are commonly used in backend or service-style code and may run on ThreadPool threads. System.Timers.Timer can feel easier for beginners because it uses events.
Can I use a timer in a console application in C#?
Yes. A console application timer can use System.Threading.Timer, System.Timers.Timer, or PeriodicTimer. Make sure the console app stays alive while the timer runs, usually with Console.ReadLine(), an async loop, or a hosted application pattern.
Are C# timers accurate for scheduling jobs?
C# timers are good for application-level intervals but not hard real-time scheduling. They can be affected by ThreadPool load, callback duration, system clock resolution, and app shutdown. For durable production scheduling, consider a hosted service, queue, database-backed job scheduler, or cloud scheduler.
Microsoft Learn: .NET timers
Microsoft Learn: System.Threading.Timer
Microsoft Learn: System.Timers.Timer
Microsoft Learn: System.Windows.Forms.Timer