C# 中常用的定时器详解

C# 中常用的定时器主要有 4 种,分别适用于不同场景,下面我将逐一详细介绍它们的语法、使用示例及核心特性:

一、System.Threading.Timer(线程池定时器,无 UI 绑定)

这是一个轻量级定时器,基于线程池线程执行回调,不依赖 UI 线程,适用于后台任务、非 UI 场景。

核心语法
  1. 构造函数(常用重载):

    cs 复制代码
    // 参数说明:
    // callback:定时器触发时执行的回调方法(TimerCallback委托,接收object类型参数)
    // state:传递给回调方法的自定义参数(可设为null)
    // dueTime:首次触发延迟时间(TimeSpan或毫秒数,Timeout.Infinite表示永不首次触发)
    // period:后续触发的时间间隔(TimeSpan或毫秒数,Timeout.Infinite表示仅触发一次)
    public Timer(TimerCallback callback, object? state, TimeSpan dueTime, TimeSpan period);
    public Timer(TimerCallback callback, object? state, int dueTime, int period);
  2. 关键方法:

    • Change(TimeSpan dueTime, TimeSpan period):修改定时器的首次延迟和重复间隔
    • Dispose():释放定时器资源(推荐使用using语句管理)
使用示例
cs 复制代码
using System;
using System.Threading;

class ThreadingTimerDemo
{
    static void Main()
    {
        // 定义自定义状态参数
        var timerState = new { TimerName = "后台任务定时器", Count = 0 };

        // 创建定时器:首次延迟1秒,之后每2秒触发一次
        using (var timer = new Timer(TimerCallback, timerState, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2)))
        {
            Console.WriteLine("定时器已启动,按任意键停止...");
            Console.ReadKey(); // 阻塞主线程,防止程序退出
        }
    }

    // 定时器回调方法(必须匹配TimerCallback委托签名)
    private static void TimerCallback(object? state)
    {
        if (state is not { } timerState) return;
        dynamic stateObj = timerState;
        stateObj.Count++;
        Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} - {stateObj.TimerName},触发次数:{stateObj.Count}");
    }
}

二、System.Timers.Timer(基于组件的定时器,支持事件)

这是一个组件化定时器,封装了System.Threading.Timer,提供事件驱动模型,支持自动重置,同样基于线程池线程执行,适用于后台业务逻辑。

核心语法
  1. 核心属性:
    • Interval:触发间隔(毫秒数,默认 100 毫秒)
    • Enabled:是否启用定时器(true启用,false禁用,也可使用Start()/Stop()方法)
    • AutoReset:是否自动重复触发(默认true,设为false则仅触发一次)
  2. 核心事件:
    • Elapsed:定时器触发时触发的事件(事件处理方法签名:void 方法名(object sender, ElapsedEventArgs e))
  3. 关键方法:
    • Start():启用定时器(等价于Enabled = true)
    • Stop():禁用定时器(等价于Enabled = false)
    • Dispose():释放资源
使用示例
cs 复制代码
using System;
using System.Timers;

class TimersTimerDemo
{
    static int triggerCount = 0; // 记录触发次数

    static void Main()
    {
        // 创建定时器
        var timer = new System.Timers.Timer();

        // 设置属性
        timer.Interval = 2000; // 间隔2秒
        timer.AutoReset = true; // 自动重复触发
        timer.Enabled = true; // 启用定时器

        // 绑定Elapsed事件
        timer.Elapsed += Timer_Elapsed;

        Console.WriteLine("Timers定时器已启动,按任意键停止...");
        Console.ReadKey();

        // 停止并释放定时器
        timer.Stop();
        timer.Dispose();
    }

    // Elapsed事件处理方法
    private static void Timer_Elapsed(object? sender, ElapsedEventArgs e)
    {
        triggerCount++;
        Console.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss} - Timers定时器触发,次数:{triggerCount}");
    }
}

三、System.Windows.Forms.Timer(WinForm UI 定时器)

该定时器依赖 WinForm 消息循环,运行在 UI 线程上,不会造成跨线程问题,适用于更新 UI 控件(如进度条、倒计时)。

核心语法
  1. 核心属性:
    • Interval:触发间隔(毫秒数)
    • Enabled:是否启用定时器(true/false,对应Start()/Stop())
  2. 核心事件:
    • Tick:定时器触发时的事件(UI 线程执行,可直接操作 UI 控件)
  3. 关键方法:
    • Start():启用定时器
    • Stop():禁用定时器
使用示例(WinForm 项目中)
cs 复制代码
using System;
using System.Windows.Forms;

namespace WinFormTimerDemo
{
    public partial class Form1 : Form
    {
        int count = 0;
        public Form1()
        {
            InitializeComponent();

            // 1. 手动创建定时器(或通过控件面板拖拽)
            var uiTimer = new System.Windows.Forms.Timer();
            uiTimer.Interval = 1000; // 1秒间隔
            uiTimer.Tick += UiTimer_Tick;

            // 按钮控制启动/停止
            Button btnStart = new Button { Text = "启动定时器", Location = new System.Drawing.Point(10, 10) };
            Button btnStop = new Button { Text = "停止定时器", Location = new System.Drawing.Point(120, 10) };
            Label lblCount = new Label { Location = new System.Drawing.Point(10, 50), Width = 200 };

            btnStart.Click += (s, e) => uiTimer.Start();
            btnStop.Click += (s, e) => uiTimer.Stop();

            this.Controls.Add(btnStart);
            this.Controls.Add(btnStop);
            this.Controls.Add(lblCount);

            // Tick事件更新UI
            void UiTimer_Tick(object? sender, EventArgs e)
            {
                count++;
                lblCount.Text = $"UI定时器触发次数:{count},当前时间:{DateTime.Now:HH:mm:ss}";
            }
        }
    }
}

四、System.Windows.Threading.DispatcherTimer(WPF/UI 线程定时器)

该定时器是 WPF 专属,绑定 UI 线程的 Dispatcher(消息调度器),运行在 UI 线程上,可安全操作 WPF UI 控件,支持优先级设置。

核心语法
  1. 核心属性:
    • Interval:触发间隔(TimeSpan类型,推荐使用)
    • IsEnabled:是否启用定时器(true/false,对应Start()/Stop())
    • Priority:定时器执行优先级(基于 Dispatcher 优先级,默认DispatcherPriority.Normal)
  2. 核心事件:
    • Tick:定时器触发事件(UI 线程执行,无跨线程问题)
  3. 关键方法:
    • Start():启用定时器
    • Stop():禁用定时器
使用示例(WPF 项目中)
cs 复制代码
using System;
using System.Windows;
using System.Windows.Threading;

namespace WpfDispatcherTimerDemo
{
    public partial class MainWindow : Window
    {
        int tickCount = 0;
        private DispatcherTimer _dispatcherTimer;

        public MainWindow()
        {
            InitializeComponent();

            // 创建DispatcherTimer
            _dispatcherTimer = new DispatcherTimer();
            _dispatcherTimer.Interval = TimeSpan.FromSeconds(1); // 1秒间隔
            _dispatcherTimer.Priority = DispatcherPriority.Normal;
            _dispatcherTimer.Tick += DispatcherTimer_Tick;

            // 按钮控制
            var btnStart = new System.Windows.Controls.Button { Content = "启动定时器", Margin = new Thickness(10) };
            var btnStop = new System.Windows.Controls.Button { Content = "停止定时器", Margin = new Thickness(10) };
            var txtCount = new System.Windows.Controls.TextBlock { Margin = new Thickness(10) };

            btnStart.Click += (s, e) => _dispatcherTimer.Start();
            btnStop.Click += (s, e) => _dispatcherTimer.Stop();

            // 布局
            var stackPanel = new System.Windows.Controls.StackPanel { Orientation = System.Windows.Controls.Orientation.Vertical };
            stackPanel.Children.Add(btnStart);
            stackPanel.Children.Add(btnStop);
            stackPanel.Children.Add(txtCount);
            this.Content = stackPanel;

            // Tick事件更新WPF UI
            void DispatcherTimer_Tick(object? sender, EventArgs e)
            {
                tickCount++;
                txtCount.Text = $"Dispatcher定时器触发次数:{tickCount},当前时间:{DateTime.Now:HH:mm:ss}";
            }
        }
    }
}

五、四种定时器核心区别总结

定时器类型 执行线程 适用场景 核心特点
System.Threading.Timer 线程池线程 后台非 UI 任务、轻量级操作 轻量、高效、无事件模型、需手动处理线程安全
System.Timers.Timer 线程池线程 后台业务逻辑、非 UI 场景 事件驱动、支持自动重置、封装更友好
Windows.Forms.Timer WinForm UI 线程 WinForm 界面更新(进度条等) 无跨线程问题、依赖消息循环、精度较低
DispatcherTimer WPF UI 线程 WPF 界面更新、UI 交互任务 绑定 Dispatcher、支持优先级、安全操作 UI

关键注意事项

  1. 线程安全:Threading.Timer和Timers.Timer运行在线程池线程,操作共享资源时需使用lock等同步机制;
  2. 资源释放:前两种定时器需手动调用Dispose()释放资源,推荐使用using语句;
  3. 精度:UI 定时器(Forms/Dispatcher)精度较低(依赖消息循环),后台定时器精度更高;
  4. 跨线程问题:后台定时器不可直接操作 UI 控件,需通过Control.Invoke(WinForm)或Dispatcher.Invoke(WPF)切换到 UI 线程。
相关推荐
wangchunyu11424 分钟前
Python 数据可视化实战入门教程
开发语言·python·信息可视化
学逆向的2 小时前
C 突破编译器限制
c语言·开发语言·网络安全
jimy12 小时前
C++ 虚函数表:基类和派生类共用一张 vtable 吗?
开发语言·c++
爱吃提升2 小时前
Dev-C++ 5.11 C++断点调试完整教程
开发语言·c++
夜晚回家2 小时前
Python 原始字符串详解 | r 前缀到底让什么不再转义
开发语言·python
陈年老古董2 小时前
PyQt5 入门指南:环境搭建、PyCharm 外部工具配置与登录界面实战
开发语言·qt·pycharm
看浪的路人2 小时前
第7讲:大模型后端服务化——Go 实现高并发 LLM Proxy / Router / Fallback
开发语言·后端·golang
iCxhust3 小时前
Matlab求解发电机的极限切除角
开发语言·算法·matlab·电力系统
zhanghaha13143 小时前
Qt 类完整例程【逐词拆解 + 逐步骤执行保姆教程】
开发语言·qt
samble3 小时前
从零搭建灌装监控系统(十八):自定义控件,三色灯与状态指示
c#·wpf·mvvm·modbus·工业控制