在C#中,实现定时器功能有多种方式,下面将介绍最常用的几种定时器实现方法,包括它们的特性、适用场景和示例代码。
实现方法
Timers.Timer
这是最常用的定时器,适用于需要在特定时间间隔触发事件的场景。
优点:
-
使用方便
-
基于线程池工作
-
可以设置AutoReset属性控制是否自动重复
缺点:
-
精度有限,约为10-20毫秒
-
如果事件处理时间超过间隔,可能导致事件堆积
适用场景:
-
后台服务
-
服务器应用程序
-
需要定期执行但不要求高精度的任务
cs
using System;
using System.Timers;
public class TimerExample
{
private static Timer timer;
public static void Main()
{
// 创建定时器,间隔1000毫秒(1秒)
timer = new Timer(1000);
// 绑定Elapsed事件
timer.Elapsed += OnTimedEvent;
// 设置定时器自动重置(默认为true)
timer.AutoReset = true;
// 启用定时器
timer.Enabled = true;
Console.WriteLine("按任意键退出...");
Console.ReadKey();
// 停止定时器
timer.Stop();
timer.Dispose();
}
private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
Console.WriteLine($"定时事件触发于: {e.SignalTime:HH:mm:ss.fff}");
}
}
Threading.Timer
轻量级的线程池定时器,适合需要高性能的场景。
优点:
-
最轻量级的定时器
-
直接使用线程池
-
性能最好
-
可以动态更改间隔时间
缺点:
-
只有回调没有事件,使用稍复杂
-
回调中异常会导致整个应用程序崩溃
适用场景:
-
高性能后台任务
-
需要频繁创建/销毁定时器的场景
cs
using System;
using System.Threading;
public class ThreadingTimerExample
{
private static Timer timer;
public static void Main()
{
// 创建定时器:第一个参数是回调方法,第二个是状态对象,
// 第三个是延迟时间(毫秒),第四个是间隔时间(毫秒)
timer = new Timer(TimerCallback, null, 0, 1000);
Console.WriteLine("按任意键退出...");
Console.ReadKey();
// 释放定时器资源
timer.Dispose();
}
private static void TimerCallback(object state)
{
Console.WriteLine($"定时回调触发于: {DateTime.Now:HH:mm:ss.fff}");
}
}
Diagnostics.Stopwatch + 异步循环
优点:
-
可实现最高精度
-
完全控制执行流程
-
可适应复杂调度需求
缺点:
-
实现较复杂
-
需要手动处理各种边界情况
适用场景:
-
游戏循环
-
多媒体处理
-
需要精确时间控制的场景
cs
using System;
using System.Diagnostics;
using System.Threading.Tasks;
public class HighPrecisionTimer
{
public static async Task Start(int intervalMs, Action action, CancellationToken cancellationToken)
{
var stopwatch = new Stopwatch();
stopwatch.Start();
long nextTrigger = 0;
while (!cancellationToken.IsCancellationRequested)
{
long elapsed = stopwatch.ElapsedMilliseconds;
if (elapsed >= nextTrigger)
{
action();
nextTrigger = elapsed + intervalMs;
}
// 减少CPU占用
await Task.Delay(1, cancellationToken);
}
}
public static async Task Main()
{
var cts = new CancellationTokenSource();
Console.WriteLine("按任意键停止...");
// 启动高精度定时器,每100毫秒执行一次
var timerTask = Start(100, () => {
Console.WriteLine($"高精度定时器触发: {DateTime.Now:HH:mm:ss.fff}");
}, cts.Token);
Console.ReadKey();
cts.Cancel();
try { await timerTask; } catch (TaskCanceledException) {}
}
}
PeriodicTimer
.NET 6引入的新定时器,专为异步场景设计。
优点:
-
专为异步设计
-
使用简单直观
-
与CancellationToken集成良好
缺点:
-
仅限.NET 6及以上版本
-
精度中等
适用场景:
-
现代异步应用程序
-
需要与其他异步操作集成的定时任务
cs
using System;
using System.Threading;
using System.Threading.Tasks;
public class PeriodicTimerExample
{
public static async Task Main()
{
using var timer = new PeriodicTimer(TimeSpan.FromSeconds(1));
while (await timer.WaitForNextTickAsync())
{
Console.WriteLine($"PeriodicTimer触发于: {DateTime.Now:HH:mm:ss.fff}");
}
}
}
Windows.Forms.Timer
Windows窗体应用程序专用的定时器,事件在UI线程上执行。
优点:
-
专门用于Windows窗体应用
-
Tick事件在UI线程执行,可直接操作UI控件
-
使用简单
缺点:
-
精度最低(约55ms)
-
如果Tick处理耗时会导致UI卡顿
适用场景:
-
Windows窗体应用程序
-
需要更新UI的定时操作
cs
using System;
using System.Windows.Forms;
public class FormsTimerExample : Form
{
private Timer timer;
public FormsTimerExample()
{
timer = new Timer();
timer.Interval = 1000; // 1秒
timer.Tick += Timer_Tick;
timer.Start();
}
private void Timer_Tick(object sender, EventArgs e)
{
Console.WriteLine($"窗体定时器触发于: {DateTime.Now:HH:mm:ss.fff}");
}
[STAThread]
public static void Main()
{
Application.Run(new FormsTimerExample());
}
}
对比
定时器类型 | 精度 | 线程模型 | 适用场景 |
---|---|---|---|
System.Timers.Timer | 中等(10~20ms) | 线程池 | 服务器应用、后台服务 |
System.Threading.Timer | 中等(10~20ms) | 线程池 | 高性能需求、后台任务 |
System.Windows.Forms.Timer | 低(~55ms) | UI线程 | Windows窗体应用 |
Stopwatch+异步循环 | 高(1ms) | 自定义 | 游戏、多媒体、高精度需求 |
PeriodicTimer (.NET 6+) | 中等 | 异步 | 现代异步应用 |
选择定时器时应考虑以下因素:
-
执行环境:
-
Windows窗体应用 → System.Windows.Forms.Timer
-
WPF应用 → DispatcherTimer
-
控制台/服务 → System.Timers.Timer 或 System.Threading.Timer
-
现代异步应用 → PeriodicTimer
-
-
精度需求:
-
普通需求(秒级):任意定时器
-
中等需求(10-50ms):System.Timers.Timer 或 System.Threading.Timer
-
高精度需求(1ms):Stopwatch+异步循环
-
-
线程要求:
-
需要更新UI → UI线程定时器(Forms.Timer/DispatcherTimer)
-
后台执行 → 线程池定时器(Timers.Timer/Threading.Timer)
-
-
.NET版本:
-
.NET 6+ → 优先考虑PeriodicTimer
-
旧版本 → 选择其他适合的定时器
-
-
功能需求:
-
需要动态调整间隔 → System.Threading.Timer
-
需要简单事件模型 → System.Timers.Timer
-
需要复杂调度逻辑 → Stopwatch+自定义循环
-