网上代码一:
LARGE_INTEGER PT_litmp;
LONGLONG PT_QPart1,PT_QPart2;
double PT_dfMinus,PT_dfFreq,PT_dfTim;
(以上的LARGE_INTEGER 和LONGLONG数据结构你查msdn)
QueryPerformanceFrequency(&PT_litmp);
PT_dfFreq=(double)PT_litmp.QuadPart;//获得系统的主频
QueryPerformanceCounter(&PT_litmp);
PT_QPart1=PT_litmp.QuadPart; //获得起始的值
do{
QueryPerformanceCounter(&PT_litmp);
PT_QPart2=PT_litmp.QuadPart; //获得结束计数
PT_dfMinus=(double)(PT_QPart2-PT_QPart1);
PT_dfTim=PT_dfMinus/PT_dfFreq; //计算出程序运行的时间,单位s
}while(PT_dfTim*1000000<1000); //当程序运行到1000ns时退出while循环
我在vc6.0下通过
网上代码二:
#include "stdafx.h"
#include "windows.h"
int main(int argc, char* argv[])
{
LARGE_INTEGER countstart;
LARGE_INTEGER countend;
__int64 timediff;
LARGE_INTEGER frequent;
QueryPerformanceCounter( &countstart);
printf("Hello World!/n");
printf("Hello World!/n");
printf("Hello World!/n");
QueryPerformanceCounter( &countend);
timediff = (__int64)countend.QuadPart-(__int64)countstart.QuadPart;
QueryPerformanceFrequency(&frequent);
double dsec = (double)timediff/(double)frequent.QuadPart;
printf("elapsed time :%f(second)/n",dsec);
return 0;
}
网上贴二:
一般的实时控制,使用GetTickCount()函数就可以满足精度要求,
但要进一步提高计时精度,就要采用QueryPerformanceFrequency()函数和QueryPerformanceCounter()函数
偶在做一个高度表软体时候用到过后面的两个API
感觉效果不错,你可以尝试尝试
-------------------------------------------------------------------------------
三种Windows中的定时或计时方法
--------------------------------------------------------------------------------
---- 随着软硬件的飞速发展,计算机技术已经广泛地应用到自动化控制领域,为了实现实时控制,控制程序应该能够精确地完成定时和计时。Visual C++提供了很多关于时间操作的函数,下面根据它们精度的不同,分别进行说明。
---- 任何Visual C++的程序员都会利用Windows的WM_TIMER消息映射来进行简单的时间控制:1、调用函数SetTimer()设置定时间隔,如SetTimer(0,200,NULL)即为设置200毫秒的时间间隔;2、在应用程序中增加定时响应函数OnTimer(),并在该函数中添加响应的处理语句,用来完成定时时间到时的操作。这种定时方法是非常简单的,但其定时功能如同Sleep()函数的延时功能一样,精度非常低,只可以用来实现诸如位图的动态显示等对定时精度要求不高的情况,但在精度要求较高的条件下,这种方法应避免采用。
---- 在要求误差不大于1毫秒的情况下,可以采用GetTickCount()函数(如果读者仍然使用Windows3.1,可以使用GetCurrentTime()函数),该函数的返回值是DWORD型,表示以毫秒为单位的计算机启动后经历的时间间隔。使用下面的编程语句,可以实现50毫秒的精确定时,其误差小于1毫秒。以下语句已经使用在大连理工大学海岸和近海工程国家重点实验室为广东省水利水电科学研究所研制开发的液压伺服多向不规则造波机系统的控制程序中。
DWORD dwStart, dwStop ; // 起始值和中止值
dwStop = GetTickCount();
while(TRUE)
{
dwStart = dwStop ; // 上一次的中止值变成新的起始值
// …… 此处添加相应控制语句 ……
do
{
dwStop = GetTickCount() ;
} while(dwStop - 50 < dwStart) ;
}
---- 对于一般的实时控制,使用GetTickCount()函数就可以满足精度要求。但作者在为大连基康公司编写快速计数程序时,发现使用GetTickCount()函数对计数结果产生很大影响。为了进一步提高计时精度,作者使用了QueryPerformanceFrequency()函数和QueryPerformanceCounter()函数。这两个函数是Visual C++提供的仅供Windows 95及其后续版本使用的高精度时间函数,并要求计算机从硬件上支持高精度计时器。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)litmp.QuadPart ;
QueryPerformanceCounter(&litmp) ;
// 获得初始值
QPart1 = litmp.QuadPart ;
Sleep(100) ;
QueryPerformanceCounter(&litmp) ;
// 获得中止值
QPart2 = litmp.QuadPart ;
dfMinus = (double)(QPart2 - QPart1) ;
dfTim = dfMinus / dfFreq ;
// 获得对应的时间值
---- 执行上面程序,得到的结果为dfTim=0.097143767076216(秒),细心的读者会发现,每次执行的结果都不一样,存在一定的差别,这是由于Sleep()自身的误差所致。
---- 本文介绍了三种定时或计时的实现方法,读者可以根据自己的实际情况进行选择,以达到程序的定时和计时功能。以上程序均使用Visual C++5.0和6.0在Windows98下调试通过。
c++获取windows时间的方法(转)
介绍
我们在衡量一个函数运行时间,或者判断一个算法的时间效率,或者在程序中我们需要一个定时器,定时执行一个特定的操作,比如在多媒体中,比如在游戏中等,都会用到时间函数。还比如我们通过记录函数或者算法开始和截至的时间,然后利用两者之差得出函数或者算法的运行时间。编译器和操作系统为我们提供了很多时间函数,这些时间函数的精度也是各不相同的,所以,如果我们想得到准确的结果,必须使用合适的时间函数。现在我就介绍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_time.GetTotalSeconds() < 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 3.5以及以后版本精度是10ms,它的时间精度比clock函数的要高,GetTickCount()常用于多媒体中。
7 : Windows 下timeGetTime
使用: 需要包含 Mmsystem.h , Windows.h ,加入静态库 Winmm.lib.
timeBeginPeriod(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 << (nEndTime.QuadPart-m_nBeginTime.QuadPart)*1000/m_nFreq.QuadPart << endl;
原理: CPU上也有一个计数器,以机器的clock为单位,可以通过rdtsc读取,而不用中断,因此其精度与系统时间相当。
精度: 计算机获取硬件支持,精度比较高,可以通过它判断其他时间函数的精度范围。
10 小结: 以上提到常用的9种时间函数,由于他们的用处不同,所以他们的精度也不尽相同,所以如果简单的延时可以用sleep函数,稍微准确的延时可以使用clock函数,GetTickCount函数,更高级的实用 timeGetTime函数;简单的定时事件可以用Timer,准确地可以用timeSetEvent;或取一般系统时间可以通time,或者 CTime,或者COleDateTime,获取准确的时间可以用clock,或者GetTickCount函数,或者timeGetTime函数,而获取准确地系统时间要使用硬件支持的QueryPerformanceFrequency函数,QueryPerformanceCounter函数。