首页 游戏 软件 资讯 排行榜 专题
首页
编程语言
C# Timer定时器的使用方法与常见示例详解

C# Timer定时器的使用方法与常见示例详解

热心网友
60
转载
2026-05-06

选错 Timer 类型是 C# 定时任务出问题的最常见原因

c#如何使用Timer定时器_c#Timer定时器的几种常见方法

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈

在 C# 中实现定时任务,代码本身可能没错,但问题往往出在第一步:用错了 Timer 类。这就像用螺丝刀去敲钉子,工具不对,活儿自然干不好。比如,在控制台程序里误用 System.Windows.Forms.Timer,定时器压根不会触发;反过来,在 UI 线程里用 System.Threading.Timer 直接更新控件,等待你的就是一个跨线程异常;如果想用 await 等待定时任务,却选了老式的同步回调模型,主线程被阻塞也就不奇怪了。

说到底,C# 提供了多种 Timer,各有其明确的适用场景。选对类型,问题就解决了一半。

System.Threading.Timer:后台任务、无 UI 场景的首选

这是最轻量级的选手,纯粹基于线程池执行回调,不依赖任何 UI 框架。因此,它是控制台应用、后台服务或 Worker Service 的理想选择。不过,它的回调执行在非 UI 线程上,这意味着你不能直接在其中操作像 TextBox.Text 这样的控件。

  • 构造与异常处理:构造时需要传入一个 TimerCallback 委托。这里有个关键细节:务必在委托内部捕获并处理异常。否则,一旦回调抛出未捕获的异常,定时器就会“静默”停止工作,不报错也不继续执行,排查起来相当棘手。
    var timer = new Timer(_ => {
        try
        {
            DoWork();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex}");
        }
    }, null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(5));
  • 动态调整:通过 Change() 方法可以动态改变触发间隔。需要注意的是,第一个参数 dueTime 指的是下一次触发距离现在的延迟时间,而不是一个绝对的起始偏移量。将其设为 TimeSpan.Zero 则表示立即触发下一次。
  • 资源释放:必须手动调用 Dispose() 来释放其占用的线程池资源。推荐使用 using 语句块或在适当生命周期内显式释放,以避免资源泄漏。

System.Timers.Timer:需要事件模型 + 自动重置的后台服务

这个类可以看作是 System.Threading.Timer 的一个封装,提供了更清晰的 Elapsed 事件模型,并且支持 AutoReset(自动重置)和 Enabled 等属性,语义上更直观。但本质上,它的回调仍然在线程池线程上触发。

  • UI 线程访问:在 Elapsed 事件处理器中,同样不能直接访问 WinForms 或 WPF 的控件。更新 UI 必须通过 Control.InvokeDispatcher.Invoke 进行封送。
  • 间隔设置:其 Interval 属性单位是毫秒(double 类型),而不是 TimeSpan。将其设置为 0 是无效的,通常最小有效值为 1。
  • 停止与销毁:调用 Stop() 方法和设置 Enabled = false 效果相同,但前者意图更明确。一旦调用了 Dispose(),这个定时器实例就不能再调用 Start() 了。

System.Windows.Forms.Timer:WinForms UI 更新唯一安全的选择

这是为 WinForms 量身定制的定时器。它的 Tick 事件严格在创建它的 UI 线程上触发,因此所有控件操作都是天然线程安全的。不过,它的精度较低,实际间隔可能比设定值多出 10 到 30 毫秒,并且仅适用于 WinForms 应用程序。

  • 使用限制:它必须在窗体线程的上下文中创建和使用。在控制台程序或 WPF 应用中实例化它,它是不会工作的。
  • 间隔的合理设置Interval 单位也是毫秒。设置过小的值(比如 1 毫秒)没有意义,因为系统的消息泵处理不过来。
  • 避免耗时操作:切勿在 Tick 事件处理器中执行耗时操作,否则会导致 UI 界面卡顿。如果确实需要执行异步任务,应该在 Task.Run 中启动,并在任务完成后通过 Invoke 回到 UI 线程更新界面。

.NET 6+ 推荐:PeriodicTimer 配合 await

如果你的项目基于 .NET 6 或更高版本,并且定时任务逻辑本身是支持异步的(例如发起 HTTP 请求、读写文件),那么 PeriodicTimer 是目前最简洁、最现代的方案。它不绑定任何特定线程,也不强制使用回调,而是设计为与 await foreach 配合使用。

  • 定位与替代:它并非用来直接替代旧的 Timer 类型,而是专门为 async/await 异步流场景设计的。不能用它直接替换同步的回调逻辑。
  • 使用模式:必须搭配 async 方法和 IAsyncEnumerable 模式来使用:
    var timer = new PeriodicTimer(TimeSpan.FromSeconds(2));
    while (await timer.WaitForNextTickAsync())
    {
        await DoWorkAsync(); // 这里可以安全地使用 await
    }
  • 间隔调整:它没有提供 Change() 方法。如果需要改变触发间隔,只能将现有实例释放(Dispose),然后重新创建一个新的 PeriodicTimer

最后,有一个容易被忽略但至关重要的点:所有基于线程池的 Timer(包括 System.Threading.TimerSystem.Timers.Timer)在回调中如果发生未捕获的异常,整个定时器就会停摆。它不会自动重试,也不会将错误抛到控制台,只会静默终止。这种“故障静默”的特性,比 UI Timer 导致的“界面卡顿”更加隐蔽,也更难调试。因此,在回调内部进行完善的异常处理,不是最佳实践,而是必须遵守的生存法则。

来源:https://www.php.cn/faq/2324968.html
免责声明: 游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

相关攻略

C#怎么使用ReadOnlySpan_C#只读内存切片性能优化教程【高级】
编程语言
C#怎么使用ReadOnlySpan_C#只读内存切片性能优化教程【高级】

C ReadOnlySpan 使用指南:高性能只读内存切片优化技巧【高级教程】 在 NET 高性能编程实践中,尤其是在字符串处理场景,一个公认的高效策略是:直接采用 ReadOnlySpan 来替代传统的 string 参数以及中间的 Substring 调用。这是目前实现零分配、低开销处理的最

热心网友
05.06
c#如何实现分页查询_c#分页查询最全用法总结
编程语言
c#如何实现分页查询_c#分页查询最全用法总结

SQL Server分页首选OFFSET-FETCH,需配合ORDER BY且参数化传值;EF Core用Skip Take自动翻译,避免内存分页;大数据量时应改用游标分页。 SQL Server 中用 OFFSET-FETCH 做分页最直接 说到在SQL Server里做分页,2012及以上版本提

热心网友
05.06
c#如何批量插入数据_c#批量插入数据完整教程与实战案例
编程语言
c#如何批量插入数据_c#批量插入数据完整教程与实战案例

C 万级数据批量插入:SqlBulkCopy 实战精要 在C 中进行大规模数据插入,性能是首要考量。当数据量达到万级甚至更高时,常规的逐条插入方法会迅速成为性能瓶颈。那么,有没有一种既高效又稳定的解决方案呢?答案是肯定的。 用 SqlBulkCopy 实现高速批量插入 开门见山地说,在C 生态中,

热心网友
05.06
c#如何使用TestContainers集成测试_c#TestContainers集成测试的最佳实践与常见坑点
编程语言
c#如何使用TestContainers集成测试_c#TestContainers集成测试的最佳实践与常见坑点

C 中使用TestContainers进行集成测试:最佳实践与常见坑点 想在 NET 里玩转 TestContainers?这事儿说简单也简单,说麻烦也麻烦。简单在于,它确实能让你用几行代码就拉起一个数据库或中间件进行测试;麻烦在于,从环境配置到代码编写,每一步都有几个“经典”的坑在等着你。今天,

热心网友
05.06
C#怎么操作WPF Canvas画布绘图 C#如何在WPF Canvas上用代码动态绘制图形和连线【控件】
编程语言
C#怎么操作WPF Canvas画布绘图 C#如何在WPF Canvas上用代码动态绘制图形和连线【控件】

C WPF Canvas画布绘图完全指南:代码动态绘制图形与连线详解 Canvas直接添加子元素导致错位或不显示的解决方案 许多C 开发者在初次使用WPF Canvas控件进行动态绘图时,常会遇到一个典型问题:为何通过代码添加的Rectangle矩形或Line线条无法正常显示,或者出现位置偏移?

热心网友
05.06

最新APP

宝宝过生日
宝宝过生日
应用辅助 04-07
台球世界
台球世界
体育竞技 04-07
解绳子
解绳子
休闲益智 04-07
骑兵冲突
骑兵冲突
棋牌策略 04-07
三国真龙传
三国真龙传
角色扮演 04-07

热门推荐

POE交换机连接设备后频繁重启原因解析
电脑教程
POE交换机连接设备后频繁重启原因解析

Poe交换机带载后重启:是故障,还是系统在“自救”? 不少朋友遇到过这个头疼的问题:PoE交换机一接上设备就重启。其实,这本质上不是设备坏了,而是供电系统一套精密的自我保护机制在起作用。当负载接入的瞬间,如果系统检测到功耗超标、供电不稳等情况,就会主动触发复位,防止硬件受损。这正是IEEE 802

热心网友
05.06
电饼铛选购指南哪款型号性价比最高
电脑教程
电饼铛选购指南哪款型号性价比最高

高性价比电饼铛:精准匹配、扎实可靠、真正省心 挑选一款高性价比的电饼铛,核心其实很明确:功能要精准匹配你的真实需求,材质工艺必须扎实可靠,细节设计能让你每天用着都省心。它追求的绝不是单纯的便宜或者参数漂亮,而是每一分钱都花在刀刃上。比如,2100W级的稳定火力保证了煎烤效率不打折;0氟不粘涂层配合蜂

热心网友
05.06
红米K30 5G动态壁纸不联网可以使用吗
电脑教程
红米K30 5G动态壁纸不联网可以使用吗

红米K30 5G动态壁纸联网机制全解析 关于红米K30 5G的动态壁纸是否需要一直联网,答案是:完全没必要。这玩意儿用起来其实很“懂事”,它只在你第一次上手和偶尔想换新的时候,才需要网络搭把手。 其背后的逻辑很清晰:手机搭载的MIUI系统,把所有酷炫的动态壁纸资源都放在了小米官方的“云端仓库”里。所

热心网友
05.06
vivo Y35手机桌面时间不显示修复方法
电脑教程
vivo Y35手机桌面时间不显示修复方法

vivo Y35桌面时间不显示?别急,这事儿有解 不少vivo Y35用户可能都遇到过这个情况:一觉醒来,或者换个主题之后,主屏幕上那个熟悉的“时间”不见了。先别急着怀疑手机坏了,事实是,超过八成的类似问题,根源其实很简单——时间组件压根没被“请”上桌面,或者相关的自动设置被无意中关闭了。作为一台搭

热心网友
05.06
英雄联盟手游杰斯新皮肤获取方法与实战评测
游戏攻略
英雄联盟手游杰斯新皮肤获取方法与实战评测

英雄联盟手游杰斯新皮肤外观设计酷炫,充满科技感。技能特效以蓝色能量为主,视觉效果震撼且辨识度高。实战中技能清晰、手感流畅,能提升操作自信与战场表现。整体而言,该皮肤在视觉、特效与实战体验上均表现优异,值得玩家入手。

热心网友
05.06