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