DotNET中定时器的使用方法

.NET 中定时器的使用方法

在.NET 开发中,定时器是实现周期性任务的核心组件。根据是否依赖 UI 线程,可将其分为 “与 UI 无关联” 和 “与 UI 相关” 两大类,不同类型的定时器适用场景、线程模型及使用方式差异显著。本文将详细讲解各类定时器的特点、核心属性、正确用法及注意事项。

一、与 UI 无关联的定时器

此类定时器运行于非 UI 线程(默认使用线程池),适用于后台计算、数据同步等无需操作 UI 的场景,时间精度相对较高。

1. System.Timers.Timer

核心特点

  • 支持线程同步配置,可通过SynchronizingObject指定执行线程;

  • 事件驱动模式(通过Elapsed事件触发任务);

  • 适用于对执行精度有一定要求的后台任务。

关键属性修正

  • AutoReset:原始描述颠倒,正确逻辑为:

    • true(默认):定时器触发后自动重置,持续周期性执行;

    • false:定时器仅触发一次,执行后自动停止。

  • SynchronizingObject:默认值为null,任务运行于线程池(CPU 自动分配线程);若指定为 UI 控件(如 WinForms 的 Form),则任务会切换到 UI 线程执行。

  • Interval:任务执行间隔(单位:毫秒),最小值为 1。

  • Enabled:控制定时器是否启用(true启用,false禁用)。

正确代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
using System;

using System.Threading;

public class TimersTimerExample

{

// 声明定时器与线程同步锁(确保多线程安全)

private readonly System.Timers.Timer \_timer = new System.Timers.Timer();

private readonly object \_syncRoot = new object();

public TimersTimerExample()

{

// 绑定Elapsed事件(任务执行逻辑)

\_timer.Elapsed += OnTimerTick;

// 设置执行间隔为100毫秒

\_timer.Interval = 100;

// 配置为持续执行(AutoReset=true)

\_timer.AutoReset = true;

// 初始禁用,需手动启动

\_timer.Enabled = false;

}

// 启动定时器

public void StartTimer()

{

\_timer.Enabled = true;

// 或使用\_timer.Start()(与Enabled=true等效)

}

// 停止定时器

public void StopTimer()

{

\_timer.Enabled = false;

// 或使用\_timer.Stop()

}

// Elapsed事件回调(默认运行于线程池)

private void OnTimerTick(object sender, System.Timers.ElapsedEventArgs e)

{

// 加锁确保多线程下任务逻辑安全(避免并发问题)

lock (\_syncRoot)

{

Console.WriteLine(\$"后台任务执行:{DateTime.Now:HH:mm:ss.fff}");

// TODO:添加实际业务逻辑(如数据同步、日志记录)

}

}

}

注意事项

  • 若任务逻辑涉及共享资源,需通过lock等方式保证线程安全;

  • 若需在 UI 线程更新内容,需将SynchronizingObject指定为 UI 控件(如_timer.SynchronizingObject = this,需在 WinForms 环境中)。

2. System.Threading.Timer

核心特点

  • 轻量级定时器,完全基于线程池实现;

  • 无事件模型,通过回调函数(TimerCallback)执行任务;

  • 不支持直接指定同步对象,需手动处理线程切换。

关键参数

构造函数System.Threading.Timer(TimerCallback callback, object state, int dueTime, int period)参数说明:

  • callback:定时器触发时执行的回调函数;

  • state:传递给回调函数的参数(无需参数时设为null);

  • dueTime:定时器启动延迟时间(单位:毫秒),0表示立即启动;

  • period:任务执行间隔(单位:毫秒),Timeout.Infinite表示仅执行一次。

正确代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
using System;

using System.Threading;

public class ThreadingTimerExample

{

// 声明线程定时器(需注意释放资源)

private System.Threading.Timer \_timer;

public ThreadingTimerExample()

{

// 初始化定时器:立即启动(dueTime=0),间隔1000毫秒执行一次

\_timer = new System.Threading.Timer(

callback: TimerCallback,

state: null,

dueTime: 0,

period: 1000

);

}

// 定时器回调函数(运行于线程池)

private void TimerCallback(object state)

{

Console.WriteLine(\$"轻量级后台任务:{DateTime.Now:HH:mm:ss}");

// TODO:添加轻量级业务逻辑(如心跳检测、缓存清理)

}

// 释放定时器资源(避免内存泄漏)

public void DisposeTimer()

{

\_timer?.Change(Timeout.Infinite, Timeout.Infinite); // 先停止定时器

\_timer?.Dispose(); // 释放资源

}

}

注意事项

  • 若任务执行时间超过period,线程池会分配新线程执行下一次任务,需自行控制并发;

  • 不再使用时必须调用Dispose释放资源,避免线程泄漏;

  • 无法直接更新 UI,需通过Dispatcher(WPF)或Invoke(WinForms)切换到 UI 线程。

二、与 UI 相关的定时器

此类定时器绑定 UI 线程,适用于 WinForms、WPF 等桌面应用的 UI 更新场景,无需手动处理线程安全,但时间精度较低(受 UI 线程繁忙程度影响)。

1. System.Windows.Forms.Timer(WinForms 专用)

核心特点

  • 仅适用于 WinForms 应用,支持可视化拖拽(从工具箱拖到 Form 上);

  • 任务运行于 UI 线程,可直接更新 UI 控件(如 Label、TextBox);

  • 精度较低(约 10-55 毫秒),不适用于高时效任务。

关键属性

  • Interval:执行间隔(单位:毫秒),最小值为 1;

  • Enabled:控制定时器启用 / 禁用(true启用,false禁用);

  • Tick:定时器触发时执行的事件(运行于 UI 线程)。

正确代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
using System;

using System.Windows.Forms;

public partial class TimerForm : Form

{

// 声明WinForms定时器(可通过设计器拖拽生成)

private readonly System.Windows.Forms.Timer \_uiTimer;

public TimerForm()

{

InitializeComponent();

// 初始化定时器(代码方式,非拖拽)

\_uiTimer = new System.Windows.Forms.Timer();

\_uiTimer.Interval = 1000; // 1秒更新一次UI

\_uiTimer.Tick += UITimer\_Tick;

\_uiTimer.Enabled = true; // 启用定时器

}

// Tick事件(运行于UI线程,可直接操作控件)

private void UITimer\_Tick(object sender, EventArgs e)

{

// 直接更新Label文本(无需线程同步)

lblTime.Text = \$"当前时间:{DateTime.Now:HH:mm:ss}";

}

// 关闭窗体时释放定时器

private void TimerForm\_FormClosing(object sender, FormClosingEventArgs e)

{

\_uiTimer?.Dispose();

}

}

注意事项

  • 仅能在 WinForms 项目中使用,无法跨框架(如 WPF);

  • 若Tick事件中执行耗时操作(如循环计算),会导致 UI 卡顿;

  • 无需手动处理线程安全,因事件始终在 UI 线程执行。

2. System.Windows.DispatcherTimer(WPF 专用)

核心特点

  • 仅适用于 WPF 应用,基于Dispatcher(WPF 线程调度器)实现;

  • 任务运行于 UI 线程,支持直接更新 WPF 控件(如 TextBlock);

  • 可通过DispatcherPriority调整任务优先级(默认Normal)。

关键属性与方法

  • Interval:执行间隔(类型:TimeSpan,支持秒、毫秒等单位);

  • Tick:定时器触发事件(运行于 UI 线程);

  • **Start()/Stop()**:启动 / 停止定时器(替代Enabled属性);

  • DispatcherPriority:任务在 UI 线程中的执行优先级(如Background表示后台优先级,不阻塞 UI)。

正确代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
using System;

using System.Windows;

using System.Windows.Threading;

public partial class MainWindow : Window

{

// 声明WPF调度定时器

private readonly DispatcherTimer \_dispatcherTimer;

public MainWindow()

{

InitializeComponent();

// 初始化定时器

\_dispatcherTimer = new DispatcherTimer();

// 设置间隔为1秒(使用TimeSpan)

\_dispatcherTimer.Interval = TimeSpan.FromSeconds(1);

// 绑定Tick事件

\_dispatcherTimer.Tick += DispatcherTimer\_Tick;

// 启动定时器

\_dispatcherTimer.Start();

}

// Tick事件(运行于UI线程,可直接更新WPF控件)

private void DispatcherTimer\_Tick(object sender, EventArgs e)

{

// 直接更新TextBlock内容

tbTime.Text = \$"当前时间:{DateTime.Now:HH:mm:ss.fff}";

}

// 关闭窗口时停止定时器

private void MainWindow\_Closing(object sender, System.ComponentModel.CancelEventArgs e)

{

\_dispatcherTimer?.Stop();

}

}

注意事项

  • 仅能在 WPF 项目中使用,依赖System.Windows程序集;

  • 若需降低任务对 UI 的影响,可设置_dispatcherTimer.DispatcherPriority = DispatcherPriority.Background;

  • 若任务耗时较长,仍会导致 UI 响应缓慢,需结合Task开启后台线程处理(处理完后通过Dispatcher.Invoke更新 UI)。

三、定时器选择指南

定时器类型 适用框架 线程模型 精度 核心场景
System.Timers.Timer 通用(非 UI) 线程池(可指定同步对象) 较高 后台任务、数据同步
System.Threading.Timer 通用(非 UI) 线程池 高 轻量级后台任务(如心跳检测)
System.Windows.Forms.Timer WinForms UI 线程 较低 WinForms UI 更新
System.Windows.DispatcherTimer WPF UI 线程 较低 WPF UI 更新

总结:需根据项目框架(WinForms/WPF/ 控制台)、是否操作 UI、精度要求三大因素选择定时器,避免因线程模型不匹配导致 UI 卡顿或数据安全问题。