1、精确获取时间精确获取时间(QueryPerformanceCounter)LARGE_INTEGER tima,timb;QueryPerformanceCounter(&tima);在 Windows Server 2003 和 WindowsXP 中使用 QueryPerformanceCounter 函数的程序可能执行不当QueryPerformanceCounter 來精確計算執行時間QueryPerformanceCounter 來精確計算執行時間/ 這個程式展示了如何使用QueryPerformanceCounter 來精確計算執行時間/代码1. LARGE_INTEGERm_li
2、PerfFreq=0;2. /获取每秒多少CPUPerformanceTick3. QueryPerformanceFrequency(&m_liPerfFreq);4. 5. LARGE_INTEGERm_liPerfStart=0;6. QueryPerformanceCounter(&m_liPerfStart);7. 8. for(inti=0;i100;i+)9. coutiendl;10. 11. LARGE_INTEGERliPerfNow=0;12. /计算CPU运行到现在的时间13. QueryPerformanceCounter(&liPerfNow);14. 15. in
3、ttime=(liPerfNow.QuadPart-m_liPerfStart.QuadPart)*1000)/m_liPerfFreq.QuadPart);16. 17. charbuffer100;18. sprintf(buffer,執行時間%dmillisecond,time);19. 20. coutbufferendl;21. 22. QueryPerformanceCounter()这个函数返回高精确度性能计数器的值,它可以以微妙为单位计时.但是QueryPerformanceCounter()确切的精确计时的最小单位是与系统有关的,所以,必须要查询系统以得到QueryPerfo
4、rmanceCounter()返回的嘀哒声的频率.QueryPerformanceFrequency()提供了这个频率值,返回每秒嘀哒声的个数.计算确切的时间是从第一次调用QueryPerformanceCounter()开始的假设得到的LARGE_INTEGER为nStartCounter,过一段时间后再次调用该函数结束的,设得到nStopCounter.两者之差除以QueryPerformanceFrequency()的频率就是开始到结束之间的秒数.由于计时函数本身要耗费很少的时间,要减去一个很少的时间开销.但一般都把这个开销忽略.公式如下: nStopCounter-nStartCoun
5、terElapsedTime=- - overheadfrequencydouble time=(nStopCounter.QuadPart-nStartCounter.QuadPart)/frequency.QuadPart这两个函数是VC提供的仅供Windows 95及其后续版本使用的精确时间函数,并要求计算机从硬件上支持精确定时器。QueryPerformanceFrequency()函数和QueryPerformanceCounter()函数的原型如下: BOOL QueryPerformanceFrequency(LARGE_INTEGER lpFrequency); BOOL Qu
6、eryPerformanceCounter(LARGE_INTEGER lpCount);数据类型ARGE_INTEGER既可以是一个8字节长的整型数,也可以是两个4字节长的整型数的联合结构,其具体用法根据编译器是否支持64位而定。该类型的定义如下: typedef union _LARGE_INTEGER struct DWORD LowPart ;/ 4字节整型数 LONG HighPart;/ 4字节整型数 ; LONGLONG QuadPart ;/ 8字节整型数 LARGE_INTEGER ;在进行定时之前,先调用QueryPerformanceFrequency()函数获得机器内部
7、定时器的时钟频率,然后在需要严格定时的事件发生之前和发生之后分别调用QueryPerformanceCounter()函数,利用两次获得的计数之差及时钟频率,计算出事件经历的精确时间。下列代码实现1ms的精确定时:1. LARGE_INTEGERlitmp;2. LONGLONGQPart1,QPart2;3. doubledfMinus,dfFreq,dfTim;4. QueryPerformanceFrequency(&litmp);5. dfFreq=(double)litmp.QuadPart;/获得计数器的时钟频率6. QueryPerformanceCounter(&litmp);
8、7. QPart1=litmp.QuadPart;/获得初始值8. do9. 10. QueryPerformanceCounter(&litmp);11. QPart2=litmp.QuadPart;/获得中止值12. dfMinus=(double)(QPart2-QPart1);13. dfTim=dfMinus/dfFreq;/获得对应的时间值,单位为秒14. while(dfTim0.001);其定时误差不超过1微秒,精度与CPU等机器配置有关。 下面的程序用来测试函数Sleep(100)的精确持续时间: 1. LARGE_INTEGERlitmp;2. LONGLONGQPart1
9、,QPart2;3. doubledfMinus,dfFreq,dfTim;4. QueryPerformanceFrequency(&litmp);5. dfFreq=(double)litmp.QuadPart;/获得计数器的时钟频率6. QueryPerformanceCounter(&litmp);7. QPart1=litmp.QuadPart;/获得初始值8. Sleep(100);9. QueryPerformanceCounter(&litmp);10. QPart2=litmp.QuadPart;/获得中止值11. dfMinus=(double)(QPart2-QPart1
10、);12. dfTim=dfMinus/dfFreq;/获得对应的时间值,单位为秒由于Sleep()函数自身的误差,上述程序每次执行的结果都会有微小误差。下列代码实现1微秒的精确定时:1. LARGE_INTEGERlitmp;2. LONGLONGQPart1,QPart2;3. doubledfMinus,dfFreq,dfTim;4. QueryPerformanceFrequency(&litmp);5. dfFreq=(double)litmp.QuadPart;/获得计数器的时钟频率6. QueryPerformanceCounter(&litmp);7. QPart1=litmp
11、.QuadPart;/获得初始值8. do9. 10. QueryPerformanceCounter(&litmp);11. QPart2=litmp.QuadPart;/获得中止值12. dfMinus=(double)(QPart2-QPart1);13. dfTim=dfMinus/dfFreq;/获得对应的时间值,单位为秒14. while(dfTimm_hWnd,IDC_TIME,strTime);Sleep(1000);该线程函数没有参数,也不返回函数值。只要m_bRun为TRUE,线程一直运行。双击IDC_START按钮,完成该按钮的消息函数:voidCMultiThread1
12、Dlg:OnStart()/TODO:AddyourcontrolnotificationhandlercodeherehThread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadFunc,NULL,0,&ThreadID);GetDlgItem(IDC_START)-EnableWindow(FALSE);GetDlgItem(IDC_STOP)-EnableWindow(TRUE);双击IDC_STOP按钮,完成该按钮的消息函数:voidCMultiThread1Dlg:OnStop()/TODO:Addyourcontrolnoti
13、ficationhandlercodeherem_bRun=FALSE;GetDlgItem(IDC_START)-EnableWindow(TRUE);GetDlgItem(IDC_STOP)-EnableWindow(FALSE);编译并运行该例程,体会使用Win32API编写的多线程。例程2MultiThread2该线程演示了如何传送一个一个整型的参数到一个线程中,以及如何等待一个线程完成处理。建立一个基于对话框的工程MultiThread2,在对话框IDD_MULTITHREAD2_DIALOG中加入一个编辑框和一个按钮,ID分别是IDC_COUNT,IDC_START,按钮控件的标题
14、为“开始”;在MultiThread2Dlg.h文件中添加线程函数声明:voidThreadFunc(intinteger);注意,线程函数的声明应在类CMultiThread2Dlg的外部。在类CMultiThread2Dlg内部添加protected型变量:HANDLEhThread;DWORDThreadID;分别代表线程的句柄和ID。打开ClassWizard,为编辑框IDC_COUNT添加int型变量m_nCount。在MultiThread2Dlg.cpp文件中添加:voidThreadFunc(intinteger)inti;for(i=0;iEnableWindow(FALSE
15、);WaitForSingleObject(hThread,INFINITE);GetDlgItem(IDC_START)-EnableWindow(TRUE);顺便说一下WaitForSingleObject函数,其函数原型为:DWORDWaitForSingleObject(HANDLEhHandle,DWORDdwMilliseconds);hHandle为要监视的对象(一般为同步对象,也可以是线程)的句柄;dwMilliseconds为hHandle对象所设置的超时值,单位为毫秒;当在某一线程中调用该函数时,线程暂时挂起,系统监视hHandle所指向的对象的状态。如果在挂起的dwMil
16、liseconds毫秒内,线程所等待的对象变为有信号状态,则该函数立即返回;如果超时时间已经到达dwMilliseconds毫秒,但hHandle所指向的对象还没有变成有信号状态,函数照样返回。参数dwMilliseconds有两个具有特殊意义的值:0和INFINITE。若为0,则该函数立即返回;若为INFINITE,则线程一直被挂起,直到hHandle所指向的对象变为有信号状态时为止。本例程调用该函数的作用是按下IDC_START按钮后,一直等到线程返回,再恢复IDC_START按钮正常状态。编译运行该例程并细心体会。例程3MultiThread3传送一个结构体给一个线程函数也是可能的,可以
17、通过传送一个指向结构体的指针参数来完成。先定义一个结构体:typedefstructintfirstArgu,longsecondArgu,myType,*pMyType;创建线程时CreateThread(NULL,0,threadFunc,pMyType,);在threadFunc函数内部,可以使用“强制转换”:intintValue=(pMyType)lpvoid)-firstArgu;longlongValue=(pMyType)lpvoid)-seconddArgu;例程3MultiThread3将演示如何传送一个指向结构体的指针参数。建立一个基于对话框的工程MultiThread3,在对话框IDD_MULTITHREAD3_DIALOG中加入一个编辑框IDC_MILLISECOND,一个按钮IDC_START,标题为“开始”,一个进度条IDC_PROGRESS1
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1