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.TimerTimers.Timer运行在线程池线程,操作共享资源时需使用lock等同步机制;
  2. 资源释放:前两种定时器需手动调用Dispose()释放资源,推荐使用using语句;
  3. 精度:UI 定时器(Forms/Dispatcher)精度较低(依赖消息循环),后台定时器精度更高;
  4. 跨线程问题:后台定时器不可直接操作 UI 控件,需通过Control.Invoke(WinForm)或Dispatcher.Invoke(WPF)切换到 UI 线程。
相关推荐
小羊没烦恼!17 小时前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
神仙别闹18 小时前
基于C#+MySQL实现(WinForm)个人聊天室软件
c#
伞伞悦读18 小时前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
C语言小火车19 小时前
C/C++ 为什么需要编译器?
开发语言·c++
霍霍的袁20 小时前
【C++】map 和 set 的使用 | 从用法到底层
开发语言·c++·学习·visual studio
kybs199120 小时前
全球灾害数据分析可视化 毕业设计-附源码66794
vue.js·spring boot·mysql·安全·django·c#·asp.net
孙启超20 小时前
【AI开发之Rust】第 11 课:智能指针与内部可变性
开发语言·后端·rust
此生决int21 小时前
深入理解C++系列(20)——C++11(下)
开发语言·c++
CoderYanger1 天前
A.每日一题:835. 图像重叠
java·开发语言·程序人生·leetcode·面试·职场和发展·学习方法
伞伞悦读1 天前
【第37期】Python JSON 与配置详解:序列化、反序列化、嵌套结构和配置文件
开发语言·python·json