千家信息网

.NET Framework中定时器timer的单线程与多线程用法示例

发表于:2025-11-06 作者:千家信息网编辑
千家信息网最后更新 2025年11月06日,这篇文章主要介绍.NET Framework中定时器timer的单线程与多线程用法示例,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!如果你需要使用规律的时间间隔重复执行一些方法
千家信息网最后更新 2025年11月06日.NET Framework中定时器timer的单线程与多线程用法示例

这篇文章主要介绍.NET Framework中定时器timer的单线程与多线程用法示例,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

如果你需要使用规律的时间间隔重复执行一些方法,最简单的方式是使用定时器(timer)。与下边的例子相比,定时器可以便捷、高效地使用内存和资源:

new Thread (delegate() {             while (enabled)             {              DoSomeAction();              Thread.Sleep (TimeSpan.FromHours (24));             }            }).Start();

这不仅仅会永久占用一个线程,而且如果没有额外的代码,DoSomeAction每天都会发生在更晚的时间。定时器解决了这些问题。

.NET Framework 提供了 4 种定时器。下边两个类是通用的多线程定时器:

(1)System.Threading.Timer
(2)System.Timers.Timer
另外两个是专用的单线程定时器:

(3)System.Windows.Forms.Timer (Windows Forms 的定时器)
(4)System.Windows.Threading.DispatcherTimer (WPF 的定时器)
多线程定时器更加强大、精确并且更加灵活,而单线程定时器对于一些简单的更新 Windows Forms 和 WPF 控件的任务来说是安全的,并且更加便捷。

1.多线程定时器Permalink

System.Threading.Timer是最简单的多线程定时器:它仅仅有一个构造方法和两个普通方法(取悦于极简主义者,还有本书作者!)。在接下来的例子中,一个定时器在 5 秒钟之后调用Tick方法来打印 " tick… ",之后每秒打印一次直到用户按下回车键:

using System;using System.Threading;class Program{ static void Main() {  // 首次间隔 5000ms,之后间隔 1000ms  Timer tmr = new Timer (Tick, "tick...", 5000, 1000);  Console.ReadLine();  tmr.Dispose();     // 停止定时器并执行清理工作 } static void Tick (object data) {  // 这里运行在一个线程池线程上  Console.WriteLine (data);     // 打印 "tick..." }}

之后可以通过调用Change方法来改变定时器的时间间隔。如果你希望定时器只触发一次,可以指定Timeout.Infinite作为构造方法的最后一个参数。

.NET Framework 在System.Timers命名空间下提供了另一个名字相同的定时器类。它只是封装了 System.Threading.Timer,并在使用完全相同的底层引擎的前提下提供额外的便利。下面是增加功能的简介:

(1)实现了Component,允许用于 Visual Studio 的设计器中。
(2)Interval属性代替了Change方法。
(3)Elapsed事件代替了回调委托。
(4)Enabled属性用于开始或停止定时器(默认值是false)。
(5)Start和Stop方法,避免对Enabled属性感到困惑。
(6)AutoReset标识来指定是否为可重复的事件(默认为true)。
SynchronizingObject属性提供Invoke和BeginInvoke方法,用于在 WPF 和 Windows Forms 控件上安全调用方法。
这有个例子:

using System;using System.Timers;  // 命名空间是 Timers 而不是 Threadingclass SystemTimer{ static void Main() {  Timer tmr = new Timer();    // 无需任何参数  tmr.Interval = 500;  tmr.Elapsed += tmr_Elapsed;  // 使用事件代替委托  tmr.Start();          // 开启定时器  Console.ReadLine();  tmr.Stop();          // 停止定时器  Console.ReadLine();  tmr.Start();          // 重启定时器  Console.ReadLine();  tmr.Dispose();         // 永久停止定时器 } static void tmr_Elapsed (object sender, EventArgs e) {  Console.WriteLine ("Tick"); }}

多线程定时器使用线程池来允许少量线程服务多个定时器。这意味着,回调方法或Elapsed事件每次可能会在不同的线程上触发。此外,不论之前的Elapsed是否完成执行,Elapsed总是几乎按时触发。因此,回调方法或事件处理器必须是线程安全的。

多线程定时器的精度依赖于操作系统,通常是在 10-20 ms 的区间。如果需要更高的精度,你可以使用本地互操作(native interop)来调用 Windows 多媒体定时器,可以让精度提升到 1 ms。它定义在 winmm.dll 中,首先调用timeBeginPeriod来通知操作系统你需要更高的定时器精度,然后调用timeSetEvent来启动多媒体定时器。当使用完成后,调用timeKillEvent停止定时器,最后调用timeEndPeriod通知操作系统你不在需要更高的定时器精度了。可以通过搜索关键字 dllimport winmm.dll timesetevent 在网上找到完整的例子。

2.单线程定时器Permalink

.NET Framework 提供了两个定时器,为消除WPF 和 Windows Forms 应用程序的线程安全问题而设计:

System.Windows.Threading.DispatcherTimer(WPF)
System.Windows.Forms.Timer(Windows Forms)
单线程定时器不是被设计成能在其特定的环境外工作的。例如,如果在 Windows 系统服务应用程序中使用 Windows Forms 定时器,Timer事件不会触发!

它们暴露的成员都像System.Timers.Timer一样(Interval、Tick、Start和Stop),并且用法也类似。但是不同之处在于其内部是如何工作的。它们不是使用线程池来产生定时器事件,WPF 和 Windows Forms 定时器依赖于 UI 模型的底层消息循环机制(message pumping mechanism)。意味着Tick事件总是在创建该定时器的那个线程触发,在通常的程序中,它也就是管理所有 UI 元素和控件的那个线程。这有很多好处:

单线程计时器比较安全,对于更新 Windows Forms controls或者WPF这种简单任务来说更方便。在WPF或Windows Forms中安全的调用方法的SynchronizingObject对象。
单线程计时器是被设计成属于他们执行环境的计时器,如果你在一个Windows服务应用程序中使用Windows Forms的Timer,timer 事件并不会被触发,只有在对应的环境下才会被触发。
像System.Timers.Timer一样,他们也提供了相同的成员(Interval,Tick,Start,Stop),但是他们内部的工作原理不同,WPF和Windows Forms的计时器使用消息循环机制来取代线程池产生消息的机制。

你可以不必考虑线程安全。
新的Tick在之前的Tick完成执行前不会触发。
你可以直接在Tick时间事件的处理代码中更新 UI 控件,而不需要调用Control.Invoke或Dispatcher.Invoke。
这听起来好的难以置信,直到你意识到使用这些定时器的程序并不是真正的多线程,不会有并行执行。一个线程服务于所有定时器,并且还处理 UI 事件。这带来了单线程定时器的缺点:

除非Tick事件处理器执行的很快,否则 UI 会失去响应。
这使得 WPF 和 Windows Forms 定时器仅适用于小任务,通常就是那些更新 UI 外观的任务(例如,显示时钟或倒计时)。否则,你就需要多线程定时器。

在精度方面,单线程定时器与多线程定时器类似(几十毫秒),但是通常精度更低,因为它们会被其它 UI 请求(或其它定时器事件)推迟。

单线程计时器基于Windows消息循环,应用程序会同步的处理计时器的消息。会发现UI界面相应速度比较慢。解决这个问题的方法是使用多线程计时器。
单线程计时器的缺点:除非Tick事件的处理代码执行的非常快,否则UI界面会变得响应很慢。所以 WPF和Windows Forms的计时器都非常适合小任务,尤其是界面更新的任务。例如时钟和计数显示。否则,你需要一个多线程计时器

以上是".NET Framework中定时器timer的单线程与多线程用法示例"这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注行业资讯频道!

定时器 线程 事件 方法 计时器 安全 精度 任务 程序 处理 消息 更新 两个 例子 属性 应用程序 控件 时间 系统 应用 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 嘉兴物联网智慧工厂软件开发 网络安全管理情况的说明 软件开发linux系统电脑推荐 删除数据库某一年的数据 校园网络安全小组工作职责 网络安全宣传手抄报模板 关于防护网络安全的美文 蜀山论剑网络安全大会 计算机网络技术发展历史 嘉定区专业网络技术零售价格 创建数据库至少包括几个 哪个大学开放了网络安全专业 校园卡管理系统数据库图表 计算机网络技术职业倾向 福建省信息技术数据库 数据库中格式控件属性 第七届网络安全活动 xcom2服务器无法连接 天津创科网络技术有限公司 淮安创新软件开发售后服务 不能还原微赞数据库 韶关手机游戏软件开发分析 视频聊天收费软件开发 软件开发技术工具 实际存储在数据库中的表是 大足区常规软件开发流程要求 成都喵掌门网络技术有限公司 网络技术岗位职责 csgo怎么进入社区服务器列表 Oracle数据库返回码
0