跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

C#如何实现定时任务_C#使用Timer定时器执行操作【笔记】

应根据场景选择:System.Timers.Timer适合WinForms/WPF需线程安全事件的UI更新(注意Invoke),System.Threading.Timer适合后台服务(需手动try/catch异常、强引用防GC回收、Dispose释放资源);Web应用应改用IHostedService。 直接用
System.Timers.Timer
或
System.Threading.Timer
就能跑定时任务,但选错类型、没处理好线程上下文或忘了释放资源,5分钟写的代码可能跑两天就挂了。 用
System.Timers.Timer
还是
System.Threading.Timer
? 前者是基于事件的、线程安全的、适合 WinForms/WPF 主动触发 UI 更新(需注意跨线程);后者是轻量级委托回调、无事件模型、回调在线程池线程上执行,适合后台服务类定时操作。
System.Timers.Timer
的
Elapsed
事件默认在 ThreadPool 线程触发,不能直接更新 WinForms 控件,得用
Control.Invoke
或 WPF 的
Dispatcher.Invoke
System.Threading.Timer
不抛异常到主线程——如果回调里崩了,你根本收不到错误,建议包一层
try/catch
Web 应用(如 ASP.NET Core)别用这两个做长期定时任务,IIS 可能回收进程或应用池休眠,应改用
IHostedService
+
BackgroundService
Timer
启动后不触发?常见原因 最常踩的坑不是代码写错,而是对象被 GC 提前回收了——尤其
System.Threading.Timer
没被任何变量引用时,哪怕设置了
dueTime
,也可能秒退。 C知道 CSDN推出的一款AI技术问答工具 下载 必须持有对 Timer 实例的强引用,比如存为类字段:
private Timer _timer;
,而不是局部变量
System.Timers.Timer.AutoReset
默认为
true
,设成
false
后只触发一次,记得手动调
Start()
Interval
单位是毫秒,写
1000
是 1 秒,写
60
是 60 毫秒,别手抖少个零 首次触发延迟由
dueTime
(
Threading.Timer
)或
Start()
调用时机决定,不是从构造就开始倒计时 如何安全停止并释放
Timer
不显式
Dispose()
或
Stop()
,Timer 会一直占着线程池资源,甚至阻止应用退出。
System.Timers.Timer
:调
Stop()
+
Dispose()
,且建议在
finally
或
IDisposable.Dispose()
中做
System.Threading.Timer
:调
Dispose()
即可,它内部自动取消所有待执行回调 别在回调里直接
Dispose()
当前 Timer——可能正处在回调执行中,要等回调退出后再 Dispose,或者用
Interlocked.CompareExchange
加锁控制状态 如果 Timer 是单例或静态的,注意多线程并发 Stop/Dispose,加锁或用
Lazy
初始化 真正麻烦的不是怎么启动 Timer,而是它跑着跑着突然不响了——往往因为没捕获回调异常、没保持引用、或部署环境限制了后台线程存活。留个心眼:加日志、设超时兜底、别信“它一直都在”。

相关文章