Timer控件-Forms.Timer\System.Timers.Timer\System.Threading.Timer
Timer控件主要有三种分别是:
1、Forms.Timer
2、System.Timers.Timer
3、System.Threading.Timer
1、Forms.Timer
常用属性:Interval,Enabled
事件:Tick
知识点1:
启动timer的方法:
可以使用timer1.Enabled=true;
也可以使用timer1.Start();
知识点2:
Forms.Timer的精度很差,当单次执行时间超过间隔时间,会影响下次触发,精度很差。
知识点3:
Forms.Timer使用UI主线程,可以修改UI元素;
private void FormPictureBox_Load(object sender, EventArgs e) { Console.WriteLine("ui线程"+Thread.CurrentThread.ManagedThreadId); timer1.Interval = 2000; timer1.Enabled = true; timer1.Start(); } private void timer1_Tick(object sender, EventArgs e) { Console.WriteLine("timer1:"+Thread.CurrentThread.ManagedThreadId); }
结果:
2、System.Timers.Timer
System.Timers.Timer 基于服务,轻量
知识点1:
属性:Interval,控制时间间隔
属性:AutoReset,控制单次执行还是重复执行
属性:Enabled,控制定时器启动,或者使用Start()方法启动定时器,Stop()方法关闭定时器
事件:Elapsed,执行操作
知识点2:
System.Timers.Timer 的Elapsed事件中执行的操作不是由UI线程执行的,
所以不可以直接修改UI元素,可以通过UI元素的Invoke(new Action())完成,在委托里修改UI元素。
举例:实现显示事件,效果如下:
代码:
private void FormTimer1_Load(object sender, EventArgs e) { System.Timers.Timer timer = new System.Timers.Timer(); timer.Interval = 1000; timer.AutoReset = true; timer.Elapsed += Timer_Elapsed; //timer.Start();//使用Start方法启动 timer.Enabled=true;//使用Enabled属性启动 Console.WriteLine("UI线程:"+Thread.CurrentThread.ManagedThreadId); } private void Timer_Elapsed(object sender, ElapsedEventArgs e) { Console.WriteLine("timer线程:"+ Thread.CurrentThread.ManagedThreadId); this.Invoke(new Action(() => { label2.Text = System.DateTime.Now.ToString(); Console.WriteLine("委托线程:" + Thread.CurrentThread.ManagedThreadId); })); }
输出:
从输出结果可以看出:
Timer_Elapsed事件中执行的内容是在新建线程中执行的,而修改label2.Text的委托实在主线程中执行的。
知识点3:
不用于Forms.Timer,对于耗时操作(耗时事件超过Timer设置的时间间隔),不会影响下一次触发,不会使UI失去响应。
例如,在Timer_Elapsed事件中执行线程休眠3秒操作,不会影响下一次触发
private void Timer_Elapsed(object sender, ElapsedEventArgs e) { Console.WriteLine("timer线程:"+ Thread.CurrentThread.ManagedThreadId); this.Invoke(new Action(() => { label2.Text = System.DateTime.Now.ToString(); Console.WriteLine("委托线程:" + Thread.CurrentThread.ManagedThreadId); })); Thread.Sleep(3000); }
输出:
从输出结果中可以看到,对于没有执行完的Timer_Elapsed事件内容,会新建一个线程执行Timer_Elapsed事件
知识点4:
线程的终止:
实例,执行如下效果:
代码:
System.Timers.Timer timer1; private void FormTimer1_Load(object sender, EventArgs e) { timer1 = new System.Timers.Timer(); timer1.Interval = 100; timer1.AutoReset = true; timer1.Elapsed += Timer1_Elapsed; //timer.Start();//使用Start方法启动 timer1.Enabled = true;//使用Enabled属性启动 } int num = 0; int result = 0; private void Timer1_Elapsed(object sender, ElapsedEventArgs e) { this.Invoke(new Action(() => lblNumber.Text = num.ToString())); if (num <= 100) { result += num; num++; this.Invoke(new Action(() => lblResul.Text = result.ToString())); } else { timer1.Stop(); } }
问题:当任务没有执行完就关闭程序时,会报错,如下:
报错内容显示,UI线程已经关闭,但是Timer1_Elapsed事件中要执行修改UI元素的任务导致的报错!
解决方法:在窗体关闭时关闭timer,并在窗体关闭后结束进程。
private void FormTimer1_FormClosing(object sender, FormClosingEventArgs e) { if (timer1.Enabled == true) timer1.Stop(); } private void FormTimer1_FormClosed(object sender, FormClosedEventArgs e) { System.Environment.Exit(0);//结束进程 }
3、System.Threading.Timer
System.Threading.Timer与System.Timers.Timer功能相似,都是基于服务,轻量,精度高。
System.Threading.Timer提供以指定的时间间隔对线程池执行方法的机制
执行单次运行过长的任务不会影响下次的触发,采用回调方法执行操作。
不可以直接修改UI元素,需要使用UI元素的Invoke()来实现
知识点1:
代码:
System.Threading.Timer timer1; private void FormTimer2_Load(object sender, EventArgs e) { timer1 = new System.Threading.Timer(new System.Threading.TimerCallback(o => { this.Invoke(new Action(() => { label2.Text = System.DateTime.Now.ToString(); })); }), null, 100, 1000); }
在new System.Threading.Timer的构造函数中,第一个参数是回调函数,第二个参数是一个object,第三个参数是延时,第四个参数是定时周期
查看回调函数的定义,如下:
回调函数需要传入一个Object类型参数,其实这个Object类型参数就是Timer构造函数中的第二个参数,举例:
输入结果如下:
知识点2:
在FlowlayoutPanel中连续添加多个lable
代码:
int count = 20; int i = 1; private void button1_Click(object sender, EventArgs e) { timer2 = new System.Threading.Timer(new System.Threading.TimerCallback(o => { Action act = addLable; this.Invoke(act); }), null, 100, 1000); } public void addLable() { if (i <= count) { Label lbl = new Label(); lbl.Name = "lbl" + i; lbl.Text = "座位" + i; lbl.Size = new System.Drawing.Size(60, 30); lbl.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; lbl.Click += Lbl_Click; flowLayoutPanel1.Controls.Add(lbl); i++; } else { timer2.Dispose(); } } private void Lbl_Click(object sender, EventArgs e) { Label lbl = sender as Label; if (lbl.BackColor != Color.Red) { lbl.BackColor = Color.Red; } else { lbl.BackColor = Color.Gray; } }
知识点3:
停止timer工作
private void FormTimer2_FormClosing(object sender, FormClosingEventArgs e) { timer1.Dispose(); timer2.Dispose(); } private void FormTimer2_FormClosed(object sender, FormClosedEventArgs e) { System.Environment.Exit(0); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)