解读 --- System.Windows.Forms.Timer是前台线程吗?
引言
今天同事问了我一个问题,System.Windows.Forms.Timer是前台线程还是后台线程,我当时想的是它是跟着UI线程一起结束的,应该是前台线程吧?
我确实没有仔细研究过他们的异同,所以带着这个疑问探究一下System.Windows.Forms.Timer。
System.Windows.Forms.Timer
机制
System.Windows.Forms.Timer 是 Windows Forms 中的一个定时器控件,它的工作原理基于 Windows 消息循环机制。
这个Windows消息循环机制说简单一点就是它有一个消息队列,一个while(true) 循环结构,一个窗口消息处理函数,消息队列保存了在应用程序或系统中发生的各种事件和消息,如鼠标点击、键盘输入、窗口重绘等。循环结构消息队列中不断取出消息。然后通过窗口消息处理函数分发给相应的窗口过程进行处理。
而 System.Windows.Forms.Timer 的事件触发机制如下:
- Timer 控件利用 Windows 的消息机制来触发 Tick 事件。在定时器启动后,它会在每个 Interval 时间间隔后,将一个
WM_TIMER消息放入应用程序的消息队列。 WM_TIMER是一个定时器消息,它是由 Windows 消息循环派发的。- 当应用程序处理消息循环时,当收到
WM_TIMER消息,就会触发 Timer 的 Tick 事件。
源码解析
来通过源码看一下它的触发机制(这里节选了部分重要函数),它的源码还是比较简单的,仅有300多行。我们先来看一下 System.Windows.Forms.Timer 的调用,一般是这样使用:
using System.Windows.Forms;
// 创建一个 Timer 实例
Timer timer = new Timer();
// 设置触发间隔时间(以毫秒为单位)
timer.Interval = 1000; // 1000 毫秒 = 1 秒
// 绑定 Tick 事件处理程序
timer.Tick += Timer_Tick;
// 启动 Timer
timer.Start();
// Tick 事件处理程序
private void Timer_Tick(object sender, EventArgs e)
{
// 定时触发的操作
}
我们就按照上面的步骤来剖析一下源码:
第一步:创建实例
这一步并无特别,无参构造默认创建的实例默认 Interval 值为100。含参构造创建时会将该实例添加到参数容器中。

第二步:注册Tick
System.Windows.Forms.Timer 声明了一个 onTimer 委托,注册 Tick 是将注册的方法赋值给 onTimer 委托。

第三步:启动Timer
可以看到Timer的 Start() 和 Stop(),实际都是给 Enabled 赋值,所以我们可以着重看一下 Enabled 属性的 Setter 方法。

第四步:TimerNativeWindow 启动
可以看到System.Windows.Forms.Timer 持有一个 TimerNativeWindow 类型的私有变量,是由这个私有变量启动的Timer.

第五步:TimerNativeWindow 实现
上一步中,可以看到当 Enable 置为 true 时,一个 TimerNativeWindow 类型的私有变量调用了 StartTimer(interval) 方法,那么来看一下这个 TimerNativeWindow 的实现。
如下图,可以看到当 TimerNativeWindow 调用 StartTimer()时,调用了 SafeNativeMethods.SetTimer 方法,传入了当前Timer的窗口句柄,还有加1后的 _timerID ,以及间隔 Interval。
该方法的作用就是向Windows消息循环机制的消息队列中插入一条Timer消息。

上图中,我除了框出了StartTimer()方法,还框出了 WndProc(ref Message m) 方法。这个方法就很重要了。这个就是上面所说的 Windows 消息循环机制中的窗口消息处理函数。
WndProc(ref Message m) 方法就是一个用于处理窗口消息的回调函数。当窗口接收到不同类型的消息时(例如鼠标事件、键盘事件、绘图事件等,包括Timer的触发事件),窗口过程会被调用来处理这些消息并作出相应的响应。
大家可能会很好奇该方法中的两个判断条件是什么意思?275 和 16 分别代表什么?
实际上这个是Windows消息标识符的十进制值。实际上他们是在名为 WinUser.h 的c++ 头文件中定义的。它随SDK一起安装到电脑上,可以通过Everything 直接找到它。

而我们要找的消息 275 和 16 就是下面这两个
- WM_TIMER :其16进制为0x0113,转化为10进制则为275。
- WM_CLOSE :其16进制为0x0010,转化为10进制则为16。

这样就可以理解WndProc(ref Message m) 方法的作用了,就是获取到 WM_TIMER 消息时,触发 System.Windows.Forms.Timer 的 OnTick 方法。而获取到 WM_CLOSE 消息时,则调用 StopTimer(),结束定时器。
结论
通过上面的机制和源码分析,可以得出结论,System.Windows.Forms.Timer 并不是线程,而是依赖于UIx线程,依赖于Windows消息循环机制而实现的定时器。
所以回到开篇的问题,这个问题本身就有问题,System.Windows.Forms.Timer 并不是线程。
解读 --- System.Windows.Forms.Timer是前台线程吗?的更多相关文章
- System.Windows.Forms.Timer与System.Timers.Timer的区别(zz)
.NET Framework里面提供了三种Timer: System.Windows.Forms.Timer System.Timers.Timer System.Threading.Timer VS ...
- System.Windows.Forms.Timer、System.Timers.Timer、System.Threading.Timer的 区别和用法
System.Windows.Forms.Timer执行的时候,如果你在过程中间加一个sleep整个的界面就死掉了,但是另外两个没有这个情况,System.Timers.Timer.System.Th ...
- 简述System.Windows.Forms.Timer 与System.Timers.Timer用法区别
System.Windows.Forms.Timer 基于窗体应用程序 阻塞同步 单线程 timer中处理时间较长则导致定时误差极大. System.Timers.Timer 基于服务 非阻塞异步 多 ...
- System.Windows.Forms.Timer、System.Timers.Timer、System.Threading.Timer的差别和分别什么时候用
System.Windows.Forms.Timer.System.Timers.Timer.System.Threading.Timer的 区别和用法http://space.itpub.net/1 ...
- System.Windows.Forms.Timer
一.主要属性.方法和事件 Windows 窗体 Timer 是定期引发事件的组件.该组件是为 Windows 窗体环境设计的. 时间间隔的长度由 Interval 属性定义,其值以毫秒为单位.若启用了 ...
- System.Windows.Forms.Timer反编译学习
using System; using System.ComponentModel; using System.Globalization; using System.Runtime; using S ...
- System.Windows.Forms.Timer的简单用法
Timer就是用来计时操作,如:你想在多少秒之后执行某个动作 Timer showTextBoxTimer = new Timer(); //新建一个Timer对象 showTextBoxTimer. ...
- System.Windows.Forms
File: winforms\Managed\System\WinForms\DataGridView.cs Project: ndp\fx\src\System.Windows.Forms.cspr ...
- .net chart(图表)控件的使用-System.Windows.Forms.DataVisualization.dll
这个案例指在介绍微软这套免费又功能强大的图表控件Microsoft Chart Controls for Microsoft .NET Framework 3.5,通过它,可让您的项目及报表,轻松套用 ...
- System.Windows.Forms.Control : Component, IOleControl, IOleObject, IOleInPlaceObject, IOleInPlaceActiveObject....
#region 程序集 System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ...
随机推荐
- cryptohack wp day(3)
第二节模运算----第一题( GCD ) 在做这道题前,了解下欧几里得算法: 欧几里得算法,也叫辗转相除法,用于求解两个非负整数a和b的最大公约数(Greatest Common Divisor, G ...
- 京喜APP - 图片库优化
作者:京东零售 何骁 介绍 京喜APP早期开发主要是快速原生化迭代替代原有H5,提高用户体验,在这期间也积累了不少性能问题.之后我们开始进行一些性能优化相关的工作,本文主要是介绍京喜图片库相关优化策略 ...
- 2022-12-05:部门工资前三高的所有员工。编写一个SQL查询找出每个部门中收入前三高的员工 。 +------------+----------+--------+ | Department |
2022-12-05:部门工资前三高的所有员工.编写一个SQL查询找出每个部门中收入前三高的员工 . ±-----------±---------±-------+ | Department | Em ...
- 2020-09-19:TCP状态有哪些?
福哥答案2020-09-19:#福大大架构师每日一题# [答案来自此链接](https://www.zhihu.com/question/421833613) 11种状态1.CLOSED状态:初始状态 ...
- 2021-02-28:给定一个整型数组arr,和一个整数num。某个arr中的子数组sub,如果想达标,必须满足:sub中最大值 – sub中最小值 <= num,返回arr中达标子数组的数量。
2021-02-28:给定一个整型数组arr,和一个整数num.某个arr中的子数组sub,如果想达标,必须满足:sub中最大值 – sub中最小值 <= num,返回arr中达标子数组的数量. ...
- 2021-06-27:给定一个正数数组arr,代表若干人的体重。再给定一个正数limit,表示所有船共同拥有的载重量。每艘船最多坐两人,且不能超过载重,想让所有的人同时过河,并且用最好的分配方法让船尽
2021-06-27:给定一个正数数组arr,代表若干人的体重.再给定一个正数limit,表示所有船共同拥有的载重量.每艘船最多坐两人,且不能超过载重,想让所有的人同时过河,并且用最好的分配方法让船尽 ...
- 2021-10-02:单词搜索。给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。单词必须按照字母
2021-10-02:单词搜索.给定一个 m x n 二维字符网格 board 和一个字符串单词 word .如果 word 存在于网格中,返回 true :否则,返回 false .单词必须按照字母 ...
- ICLR 2018-A Simple Neural Attentive Meta-Learner
Key 时序卷积+注意力机制(前者从过去的经验中收集信息,而后者则精确定位具体的信息.) 解决的主要问题 手工设计的限制:最近的许多元学习方法都是大量手工设计的,要么使用专门用于特定应用程序的架构,要 ...
- Python对两个Excel操作
简介 现在有个需求,我们根据需要 data.xlsx 中某些单元格的内容来查找 find.xlsx 中的某些內容. 数据内容(为了数据安全,所有数据均已模糊处理) data.xlsx内容: find. ...
- OCR -- 文本检测
目录 目标检测: 文本检测: 检测难点: 检测方法: 基于回归的文本检测 水平文本检测 任意角度文本检测 弯曲文本检测 基于分割的文本检测 代码示例 可视化文本检测预测 DB文本检测模型构建 back ...