关于使用线程的倒计时器的问题

openzpc 2013-05-19 10:02:07
最近在学习C#,想做一个倒计时的小程序,但是使用Timer来完成,计时总是不太准确,我在晚上看到了这个帖子http://www.cnblogs.com/yinluhui0229/archive/2012/08/20/2648313.html
里面是使用线程来实现的,但是出现的情况是:毫秒的第一位是按照秒来变的(应该是十分之一秒),而“秒”那里是10秒跳一次,请问一下这是为什么?


Timecount 是总毫秒数 每次-1
Timecount -= 1;
线程挂起时间为1毫秒
Thread.Sleep(1);

我把这个程序上传了,如果看不懂我的描述的话,可以运行一下代码就看出来了。
http://download.csdn.net/detail/openzpc/5410551

谢谢!!!


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace TimeThread
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
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 = "暂停计时";
if (isstop == 0)//第一次执行或者倒计时事件设置发生变化,则重新倒计时
{
Timecount = Convert.ToInt32(txtTotalmm.Text) * 60000;//毫秒
Thread counter = new Thread(Counter);
counter.Start();
Control.CheckForIllegalCrossThreadCalls = false;//放弃捕获对错误线程的调用,否则在线程中无法调用控件名
this.txtTotalmm.ReadOnly = true;
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();
if (Timecount == 0)
{
txthour.ForeColor = Color.Red;
txtmm.ForeColor = Color.Red;
txtss.ForeColor = Color.Red;
txtmss.ForeColor = Color.Red;
this.txtTotalmm.ReadOnly = false;
this.button1.Text = "开始计时";
isstop = 0;
try
{
Thread currthread = Thread.CurrentThread;
currthread.Abort();// 终止当前进程,会触发ThreadAbortException异常,从而终止进程,所以下面需要捕获该异常才能终止进程
}
catch (ThreadAbortException) { }
}
if (isstop != 2)
Timecount -= 1;
Thread.Sleep(1);
}
}
catch { }//处理异常关闭情况下的异常问题
}

}
}




...全文
281 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
bindofn 2013-05-20
  • 打赏
  • 举报
回复
//调用API函数 [DllImport("kernel32.dll")] extern static short QueryPerformanceCounter(ref long x); [DllImport("kernel32.dll")] extern static short QueryPerformanceFrequency(ref long x); //定义延迟函数 public void delay(long delay_Time) { long stop_Value = 0; long start_Value = 0; long freq = 0; long n = 0; QueryPerformanceFrequency(ref freq); //获取CPU频率 long count = delay_Time * freq / 1000; QueryPerformanceCounter(ref start_Value); //获取初始前值 while (n < count) //不能精确判定 { QueryPerformanceCounter(ref stop_Value);//获取终止变量值 n = stop_Value - start_Value; } } Timecount -= 1; delay(1); 去掉赋值到文本框的时间浪费,这个精度是对的
bindofn 2013-05-20
  • 打赏
  • 举报
回复
毫秒会有误差,用秒来倒数就没问题了
只在此山中 2013-05-20
  • 打赏
  • 举报
回复
只是运行了线程,没有用计时器,可以用System.Threading.Timer,大概精度有20多ms,或者用api,精度更高. Thread.Sleep(1);并不一定休眠1ms,可能大很多. Timecount单位是ms,所以代码可改: this.txtss.Text = (Timecount / 1000).ToString(); this.txtmss.Text = Timecount.ToString();
openzpc 2013-05-20
  • 打赏
  • 举报
回复
引用 3 楼 bindofn 的回复:
//调用API函数 [DllImport("kernel32.dll")] extern static short QueryPerformanceCounter(ref long x); [DllImport("kernel32.dll")] extern static short QueryPerformanceFrequency(ref long x); //定义延迟函数 public void delay(long delay_Time) { long stop_Value = 0; long start_Value = 0; long freq = 0; long n = 0; QueryPerformanceFrequency(ref freq); //获取CPU频率 long count = delay_Time * freq / 1000; QueryPerformanceCounter(ref start_Value); //获取初始前值 while (n < count) //不能精确判定 { QueryPerformanceCounter(ref stop_Value);//获取终止变量值 n = stop_Value - start_Value; } } Timecount -= 1; delay(1); 去掉赋值到文本框的时间浪费,这个精度是对的
谢谢了,我试一下

110,529

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧