
一般时控函数
VC程序员都会利用Windows的WM—TIMER消息映射来进行简单的时间控制:1调用函数SetTimer()设置定时间隔,如SetTimer(0,200,NULL)即为设置200毫秒的时间间隔;2在应用程序中增加定时响应函数OnTimer(),并在该函数中添加响应的处理语句,用来完成时间到时的 *** 作。这种定时方法是非常简单的,但其定时功能如同Sleep()函数的延时功能一样,精度较低,只可以用来实现诸如位图的动态显示等对定时精度要求不高的情况,而在精度要求较高的条件下,这种方法应避免采用。
精度时控函数
在要求误差不大于1毫秒的情况下,可以采用GetTickCount()函数,该函数的返回值是DWORD型,表示以毫秒为单位的计算机启动后经历的时间间隔。使用下面的编程语句,可以实现50毫秒的精确定时,其误差小于1毫秒。
DWORD dwStart, dwStop;
// 起始值和终止值
dwStop = GetTickCount();
while(TRUE)
{
dwStart = dwStop;
// 上一次的终止值变成新的起始值
// 此处添加相应控制语句
do
{
dwStop = GetTickCount();
} while(dwStop - 50 < dwStart);
}
高精度时控函数
对于一般的实时控制,使用GetTickCount()函数就可以满足精度要求,但要进一步提高计时精度,就要采用QueryPerformanceFrequency()函数和QueryPerformanceCounter()函数。这两个函数是VC提供的仅供Windows 9X使用的高精度时间函数,并要求计算机从硬件上支持高精度计时器。QueryPerformanceFrequency()函数和QueryPerformanceCounter()函数的原型为:
BOOL QueryPerformanceFrequency(LARGE—INTEGER *lpFrequency);
BOOL QueryPerformanceCounter(LARGE—INTEGER *lpCount) ;
数据类型LARGE—INTEGER既可以是一个作为8字节长的整型数,也可以是作为两个4字节长的整型数的联合结构,其具体用法根据编译器是否支持64位而定。该类型的定义如下:
typedef union —LARGE—INTEGER
{
struct
{
DWORD LowPart; // 4字节整型数
LONG HighPart; // 4字节整型数
};
LONGLONG QuadPart;
// 8字节整型数
} LARGE—INTEGER;
在进行计时之前,应该先调用QueryPerformanceFrequency()函数获得机器内部计时器的时钟频率。笔者在主频为266、300、333的三种PentiumⅡ机器上使用该函数,得到的时钟频率都是1193180Hz。接着,笔者在需要严格计时的事件发生之前和发生之后分别调用QueryPerformanceCounter()函数,利用两次获得的计数之差和时钟频率,就可以计算出事件经历的精确时间。以下程序是用来测试函数Sleep(100)的精确持续时间。
LARGE—INTEGER litmp;
LONGLONG QPart1,QPart2;
double dfMinus, dfFreq, dfTim;
QueryPerformanceFrequency(&litmp);
// 获得计数器的时钟频率
dfFreq = (double)litmpQuadPart;
QueryPerformanceCounter(&litmp);
// 获得初始值
QPart1 = litmpQuadPart;
Sleep(100) ;
QueryPerformanceCounter(&litmp);
// 获得终止值
QPart2 = litmpQuadPart;
dfMinus = (double)(QPart2 - QPart1);
dfTim = dfMinus / dfFreq;
// 获得对应的时间值
执行上面程序,得到的结果为dfTim=0097143767076216(秒)。细心的读者会发现,每次执行的结果都不一样,存在一定的差别,这是由于Sleep()自身的误差所致。
本文介绍了三种定时或计时的实现方法,读者可以根据自己的实际情况进行选择,以达到程序的定时和计时功能。以上程序均在VC 60、Windows 98环境下调试通过。
用的是线程函数还是MFC中的线程类?
如果是函数,把一个long型值当线程参数传入(传其地址),然后在线程中对其赋值即可。
int main(int argc,char argv[])
{
long threadTime;
beginthreadex(,threadproc,&threadTime);
//wait for thread quit
//threadTime == 线程的运行时间
}
ulong threadproc(LPVOID param)
{
long plTime = (long)param;
plTime = GetCurrentTime();
return 0;
}
如果是一个类,就直接用类变量就可以了。
看看对你有没有帮助
我们在衡量一个函数运行时间,或者判断一个算法的时间效率,或者在程序中我们需要一个定时器,定时执行一个特定的 *** 作,比如在多媒体中,比如在游戏中等,都会用到时间函数。还比如我们通过记录函数或者算法开始和截至的时间,然后利用两者之差得出函数或者算法的运行时间。编译器和 *** 作系统为我们提供了很多时间函数,这些时间函数的精度也是各不相同的,所以,如果我们想得到准确的结果,必须使用合适的时间函数。现在我就介绍windows下的几种常用时间函数。1:Sleep函数使用:sleep(1000),在Windows和Linux下1000代表的含义并不相同,Windows下的表示1000毫秒,也就是1秒钟;Linux下表示1000秒,Linux下使用毫秒级别的函数可以使用usleep。原理:sleep函数是使调用sleep函数的线程休眠,线程主动放弃时间片。当经过指定的时间间隔后,再启动线程,继续执行代码。Sleep函数并不能起到定时的作用,主要作用是延时。在一些多线程中可能会看到sleep(0);其主要目的是让出时间片。精度:sleep函数的精度非常低,当系统越忙它精度也就越低,有时候我们休眠1秒,可能3秒后才能继续执行。它的精度取决于线程自身优先级、其他线程的优先级,以及线程的数量等因素。2:MFC下的timer事件 使用:1调用函数SetTimer()设置定时间隔,如SetTimer(0,100,NULL)即为设置100毫秒的时间间隔;2在应用程序中增加定时响应函数OnTimer(),并在该函数中添加响应的处理语句,用来完成时间到时的 *** 作。 原理:同sleep函数一样。不同的是timer是一个定时器,可以指定回调函数,默认为OnTimer()函数。 精度:timer事件的精度范围在毫米级别,系统越忙其精度也就越差。3:C语言下的Time 使用:time_t t;time(&t);Time函数是获取当前时间。 原理:time函数主要用于获取当前时间,比如我们做一个电子时钟程序,就可以使用此函数,获取系统当前的时间。 精度:秒级别4:COM对象中的COleDateTime,COleDateTimeSpan类 使用:COleDateTime start_time = COleDateTime::GetCurrentTime();COleDateTimeSpan end_time = COleDateTime::GetCurrentTime()-start_time;
While(end_timeGetTotalSeconds() < 2)
{
// 处理延时或定时期间能处理其他的消息
DoSomething()
end_time = COleDateTime::GetCurrentTime-start_time;}原理:以上代表延时2秒,而这两秒内我们可以循环调用DoSomething(),从而实现在延时的时候我们也能够处理其他的函数,或者消息。COleDateTime,COleDateTimeSpan是MFC中CTime,CTimeSpan在COM中的应用,所以,上面的方法对于CTime,CTimeSpa同样有效。 精度:秒级别5:C语言下的时钟周期clock() 使用: clock_t start = clock();
Sleep(100);
clock_t end = clock();
double d = (double)(start - end) / CLOCKS_PER_SEC; 原理:clock()是获取计算机启动后的时间间隔。精度:ms级别,对于短时间内的定时或者延时可以达到ms级别,对于时间比较长的定时或者延迟精度还是不够。在windows下CLOCKS_PER_SEC为1000。6:Windows下的GetTickCount()使用: DWORD start = GetTickCount();
Sleep(100);
DWORD end = GetTickCount();原理:GetTickCount()是获取系统启动后的时间间隔。通过进入函数开始定时,到退出函数结束定时,从而可以判断出函数的执行时间,这种时间也并非是函数或者算法的真实执行时间,因为在函数和算法线程不可能一直占用CPU,对于所有判断执行时间的函数都是一样,不过基本上已经很准确,可以通过查询进行定时。GetTickCount()和Clock()函数是向主板BIOS要real time clock时间,会有中断产生,以及延迟问题。精度:WindowsNT 35以及以后版本精度是10ms,它的时间精度比clock函数的要高,GetTickCount()常用于多媒体中。7:Windows下timeGetTime使用:需要包含Mmsystemh,Windowsh,加入静态库WinmmlibtimeBeginPeriod(1);
DWORD start = timeGetTime();
Sleep(100);
DWORD end = timeGetTime();
timeEndPeriod(1);原理:timeGetTime也时常用于多媒体定时器中,可以通过查询进行定时。通过查询进行定时,本身也会影响定时器的定时精度。精度:毫秒,与GetTickCount()相当。但是和GetTickCount相比,timeGetTime可以通过timeBeginPeriod,timeEndPeriod设置定时器的最小解析精度, timeBeginPeriod,timeEndPeriod必须成对出现。8:windows下的timeSetEvent使用:还记的VC下的Timer吗?Timer是一个定时器,而以上我们提到几种时间函数或者类型,实现定时功能只能通过轮训来实现,也就是必须另外创建一个线程单独处理,这样会影响定时精度,好在windows提供了内置的定时器timeSetEvent,函数原型为MMRESULT timeSetEvent( UINT uDelay, //以毫秒指定事件的周期
UINT uResolution, //以毫秒指定延时的精度,数值越小定时器事件分辨率越高。缺省值为1ms
LPTIMECALLBACK lpTimeProc, //指向一个回调函数
WORD dwUser, //存放用户提供的回调数据
UINT fuEvent )// 标志参数,TIME_ONESHOT:执行一次;TIME_PERIODIC:周期性执行 具体应用时,可以通过调用timeSetEvent()函数,将需要周期性执行的任务定义在 lpFunction回调函数中(如:定时采样、控制等),从而完成所需处理的事件。需要注意的是:任务处理的时间不能大于周期间隔时间。另外,在定时器使用完毕后,应及时调用timeKillEvent()将之释放。原理:可以理解为代回调函数的timeGetTime精度:毫秒,timeSetEvent可以通过timeBeginPeriod,timeEndPeriod设置定时器的最小解析精度, timeBeginPeriod,timeEndPeriod必须成对出现。
9:高精度时控函数QueryPerformanceFrequency,QueryPerformanceCounter使用:LARGE_INTEGER m_nFreq;
LARGE_INTEGER m_nBeginTime;
LARGE_INTEGER nEndTime;
QueryPerformanceFrequency(&m_nFreq); // 获取时钟周期
QueryPerformanceCounter(&m_nBeginTime); // 获取时钟计数
Sleep(100);
QueryPerformanceCounter(&nEndTime);
cout << (nEndTimeQuadPart-m_nBeginTimeQuadPart)1000/m_nFreqQuadPart << endl;原理:CPU上也有一个计数器,以机器的clock为单位,可以通过rdtsc读取,而不用中断,因此其精度与系统时间相当。精度:计算机获取硬件支持,精度比较高,可以通过它判断其他时间函数的精度范围。10小结:以上提到常用的9种时间函数,由于他们的用处不同,所以他们的精度也不尽相同,所以如果简单的延时可以用sleep函数,稍微准确的延时可以使用clock函数,GetTickCount函数,更高级的实用timeGetTime函数;简单的定时事件可以用Timer,准确地可以用timeSetEvent;或取一般系统时间可以通time,或者CTime,或者COleDateTime,获取准确的时间可以用clock,或者GetTickCount函数,或者timeGetTime函数,而获取准确地系统时间要使用硬件支持的QueryPerformanceFrequency函数,QueryPerformanceCounter函数。
你需要毫秒级时间显示?如果不需要,那么long(time_t)就可以了,不需要double。
如果需要毫秒级,推荐使用COleDateTime,这个是double表示的。
COleDateTime ot(tm);ot = (double)Mytm;
Mytm = otm_dt;//return double
CString strTime = otFormat(_T("%y%m%d%H%M%S"));
CString mSec;
otGetAsSystemTime(&tm);//重启取得结构体
mSecFormat(_T(":%3d",tmwMilliseconds));
strTime += mSec;//“2014-03-17 09:10:45:440”
毫秒级时间的格式化没有标准格式,只能自己拼接。
需要注意的是,无论GetLocalTime SystemTimeToDateTime 还是 COleDateTime 其实都不是1毫秒精度,误差精度在9~56毫秒之间。
不知道你准备用什么来进行编写,下面是VC2005中的实现
系统时间可以通过
SYSTEMTIME st;
CString strDate,strTime;
GetLocalTime(&st);
来获得
你可以在程序中判断秒的值,来获得显示的值,比如说大于50秒就显示5,来实现精确到10秒
至于界面你可以用MFC 新建一对话框程序,将对话框的border属性改为none去掉标题栏那些再通过dc将你的时间展现在对话框上即可,至于颜色可以通过修改对话框着色,字体颜色来实现。
以上就是关于请教VC++高手 如何输出高精度时间差全部的内容,包括:请教VC++高手 如何输出高精度时间差、如何在MFC中获取某线程的运行时间急!、vcmfc定时器等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)