• 不要盲目选择定时器


      最近闲来无事,写了一个倒计时的小例子玩,就是想看着毫秒跳动的快感,所以首当其冲的选择了Timer,于是把Interval设置为1,于是定义timer1_Tick方法,于是运行,于是我就不淡定了,毫秒跳动不正确:三位数字只是后两位按照毫秒跳,第一位是按照秒跳的,难道1秒=100毫秒?我有些不淡定了。更蛋疼的是,秒表的跳动比正常情况下要慢,正常情况的都10秒了,它在刚过7秒……

      经过查资料发现,是Timer的Interval最小可以设置17-18,再小的话就会出现误差,看来Timer也满足不了我了。没办法,我只能选择线程,通过控制线程睡觉来控制倒计时……

    果然,线程是可以的,运行界面如图:

        

                            (设定总分钟数)                    (正在倒计时)                    (倒计时结束)

    后台代码我是这样写的:

    复制代码
    int Timecount = 0;//记录倒计时总毫秒数
            int isstop = 0;//标示是否启动/暂停的变量,0表示第一次初始化
            private void button1_Click(object sender, EventArgs e)
            {
                if (this.button1.Text == "开始计时" || this.button1.Text == "继续计时")
                {
                    this.button1.Text = "暂停计时";
                    //this.timer1.Interval = 1;
                    //this.timer1.Start();
                    if (isstop == 0)//第一次执行或者倒计时事件设置发生变化,则重新倒计时
                    {
                        Timecount = Convert.ToInt32(txtTotalmm.Text) * 60000;//毫秒
                        Thread counter = new Thread(Counter);
                        counter.Start();
                        Control.CheckForIllegalCrossThreadCalls = false;//放弃捕获对错误线程的调用,否则在线程中无法调用控件名  
                        this.txtTotalmm.ReadOnly = true;
                        this.button2.Visible = false;
                        txthour.ForeColor = Color.Black;
                        txtmm.ForeColor = Color.Black;
                        txtss.ForeColor = Color.Black;
                        txtmss.ForeColor = Color.Black;
                    }
                    isstop = 1;//启动
                }
                else
                {
                    this.button1.Text = "继续计时";
                    //this.timer1.Stop();
                    isstop = 2;//暂停
                }
            }
            public void Counter()
            {
                try
                {
                    while (Timecount >= 0)
                    {
                        this.txthour.Text = (Timecount / 3600000).ToString();
                        this.txtmm.Text = ((Timecount / 60000) % 60).ToString();
                        this.txtss.Text = ((Timecount / 1000) % 60).ToString();
                        this.txtmss.Text = (Timecount % 1000).ToString();
                        //label1.Text = hour.ToString() + "时 " + minute.ToString() + "分 " + second.ToString() + "秒" + millsecond + "毫秒";
                        if (Timecount == 0)
                        {
                            txthour.ForeColor = Color.Red;
                            txtmm.ForeColor = Color.Red;
                            txtss.ForeColor = Color.Red;
                            txtmss.ForeColor = Color.Red;
                            this.txtTotalmm.ReadOnly = false;
                            this.button2.Visible = true;
                            this.button1.Text = "开始计时";
                            isstop = 0;
                            try
                            {
                                Thread currthread = Thread.CurrentThread;
                                currthread.Abort();// 终止当前进程,会触发ThreadAbortException异常,从而终止进程,所以下面需要捕获该异常才能终止进程
                            }
                            catch (ThreadAbortException) { }                    
                        }
                        if (isstop != 2)
                            Timecount -= 1;
                        Thread.Sleep(1);
                    }
                }
                catch { }//处理异常关闭情况下的异常问题
            }
    
            private void button2_Click(object sender, EventArgs e)
            {
                this.txtTotalmm.Text = (Convert.ToInt32(this.txtTotalmm.Text) + 1).ToString();
            }
            //Timer控件的Interval频率值小于17时便会产生误差,所有得到的倒计时秒数比普通的慢很多,当倒计时精确到毫秒时,则不适用用Timer控件。        
            //private void timer1_Tick(object sender, EventArgs e)
            //{
            //    if (Timecount >= 0)
            //    {
            //        this.txthour.Text = (Timecount / 3600000).ToString();
            //        this.txtmm.Text = ((Timecount / 60000) % 60).ToString();
            //        this.txtss.Text = ((Timecount / 1000) % 60).ToString();
            //        this.txtmss.Text = (Timecount % 1000).ToString();
            //        //label1.Text = hour.ToString() + "时 " + minute.ToString() + "分 " + second.ToString() + "秒" + millsecond + "毫秒";
            //        if (Timecount == 0)
            //        {
            //            txthour.ForeColor = Color.Red;
            //            txtmm.ForeColor = Color.Red;
            //            txtss.ForeColor = Color.Red;
            //            txtmss.ForeColor = Color.Red;
            //        }
            //        Timecount -= 10;
            //    }           
            //}
    复制代码


    总结:

    1.倒计时如果是以秒为单位,可以选择Timer和线程来实现,如果以毫秒为单位,建议使用线程来实现。

    2.使用线程时,如果要暂停,需要使用Abort()方法终止线程,该方法是通过触发ThreadAbortException异常来实现对线程的终止的,所以需要捕获该异常,才能终止线程。所以     Abort()引发的该异常时正常的。

    暂时只想到了这两种方法,不知道还有没有其他的方法实现倒计时,希望大家推荐推荐……呵呵

  • 相关阅读:
    【转】MFC中png格式图片贴图的实现
    【转】Windows 中不规则窗体的编程实现
    【转】MFC添加背景图片方法的三种方法
    【转】mfc win7获得管理员权限 使用WIN7风格 使用当前系统风格
    【转】双缓冲讲解及界面贴图
    【转】[内核/驱动]驱动中获取进程全路径和注册表全路径
    【转】Visual C++中DDB与DIB位图编程全攻略(转)
    【转】vs2010中添加splashScreen
    【转】一个在内存里搜索QQ号码的源码,源自看雪论坛
    输出JSON
  • 原文地址:https://www.cnblogs.com/zxtceq/p/5894955.html
Copyright © 2020-2023  润新知