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);
        }

 

posted on 2022-10-16 23:12  hanzq_go  阅读(107)  评论(0编辑  收藏  举报

导航