感觉用API函数GetTickCount比较方便。
我的程序是这样的
var t0,TimeTaken:DWORD;
begin
 t0:=GetTickCount;
 //
 //要测量时间的程序段
 //
 TimeTaken:=GetTickCount-t0;
end;
这样就把程序段的执行时间(ms)存放在TimeTaken中了。
但是用多了发现有个问题,每次我得到的TimeTaken都是能被10整除,开始还以为是巧合,到后来发现所有的测量结果TimeTaken都是50ms,20ms,10ms,如果要测量的执行时间少于10ms测量结果TimeTaken都等于0,根本得不到正确结果。
经测量调试发现GetTickCount能得到不被10整除的毫秒数。
那么这个方法到底问题在哪儿呢?

解决方案 »

  1.   

    我的没有出现被10整除的情况。可能是与平台有关。测试代码如下:
    var i,j,beginTime,endTime : Integer;
    begin
      beginTime := GetTickCount;
      for i := 0 to 1000000 do
      begin
        for j := 0 to 1000 do
        begin
        end;
      end;
      endTime := GetTickCount;
      Edit1.Text := IntToStr((endTime - beginTime));
    end;
      

  2.   

    还有没有能精确测量时间的API函数?据说GetTickCount受操作系统时间片影响测量不准
      

  3.   

    timer的精确度一般为100ms
    gettickcount一般为10ms
    如果想再精确可以用
    QueryPerformanceCounter还有
    _int64 Count(void)
    {
    _asm _emit 0x0F
    _asm _emit 0x31
    }
    //返回CPU从上次重启到现在经历的周期数   _int64 start=Count();
      //在这里添加你的代码。
      _int64 stop=Count();
      

  4.   

    一般时控函数   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)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()自身的误差所致。   本文介绍了三种定时或计时的实现方法,读者可以根据自己的实际情况进行选择,以达到程序的定时和计时功能。以上程序均在vc 6.0、windows 98环境下调试通过。
      

  5.   

    从vc转贴的,希望对你有用基于Windows的精确定时技术在工业生产控制系统中,有许多需要定时完成的操作,如:定时显示当前时间,定时刷新屏幕上的进度条,上位机定时向下位机发送命令和传送数据等。特别是在对控制性能要求较高的控制系统和数据采集系统中,就更需要精确定时操作。   众所周知,Windows是基于消息机制的系统,任何事件的执行都是通过发送和接收消息来完成的。这样就带来了一些问题,如一旦计算机的CPU被某个进程占用,或系统资源紧张时,发送到消息队列中的消息就暂时被挂起,得不到实时处理。因此,不能简单地通过Windows消息引发一个对定时要求严格的事件。另外,由于在Windows中已经封装了计算机底层硬件的访问,所以,要想通过直接利用访问硬件来完成精确定时,也比较困难。所以在实际应用时,应针对具体定时精度的要求,采取相适应的定时方法。 VC++的时间操作函数   VC++ 中提供了很多关于时间操作的函数,利用它们控制程序能够精确地完成定时和计时操作。VC++中的WM_TIMER消息映射能进行简单的时间控制。首先调用函数SetTimer()设置定时间隔,如SetTimer(0,200,NULL)即为设置200ms的时间间隔。然后在应用程序中增加定时响应函数OnTimer(),并在该函数中添加响应的处理语句,用来完成到达定时时间的操作。这种定时方法非常简单,但其定时功能如同Sleep()函数的延时功能一样,精度非常低,只可以用来实现诸如位图的动态显示等对定时精度要求不高的情况。   在精度要求较高的情况下,如要求误差不大于1ms时,可以利用GetTickCount()函数。该函数的返回值是DWORD型,表示以ms为单位的计算机启动后经历的时间间隔。下列的代码可以实现50ms的精确定时,其误差小于1ms。 // 起始值和中止值   DWORD dwStart, dwStop ; dwStop = GetTickCount(); while(TRUE) { // 上一次的中止值变成新的起始值 dwStart = dwStop ;    // 此处添加相应控制语句    do    { dwStop = GetTickCount() ;     }while(dwStop - 50 < dwStart) ; }   对于精确度要求更高的定时操作,则应该使用QueryPerformanceFrequency()和QueryPerformanceCount er()函数。这两个函数是VC++提供的仅供Windows 95及其后续版本使用的精确时间函数,并要求计算机从硬件上支持精确定时器。QueryPerformanceFrequency()函数和QueryPerformanceCounter()函数的原型如下:   BOOL QueryPerformanceFrequency (LARGE_INTEGER *lpFrequency);   BOOL QueryPerformanceCounter (LARGE_INTEGER *lpCount); 数据类型LARGE_INTEGER既可以是一个8字节长的整型数,也可以是两个4字节长的整型数的联合结构,其具体用法根据编译器是否支持64位而定。该类型的定义如下:   typedef union _LARGE_INTEGER {    struct    { // 4字节整型数 DWORD LowPart ; // 4字节整型数 LONG HighPart ;    }; // 8字节整型数    LONGLONG QuadPart ; } LARGE_INTEGER ;   在进行定时之前,先调用QueryPerformanceFrequency()函数获得机器内部定时器的时钟频率,然后在需要严格定时的事件发生之前和发生之后分别调用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;   由于Sleep()函数自身的误差,上述程序每次执行的结果都会有微小误差。 
      

  6.   

    刚刚在VC里作了个动态连接库
    EXPORTFUNC void startcheck(DWORD* freq,DWORD* OldTime)
    { //DWORD Frequence,old,now;
     QueryPerformanceFrequency(&(union _LARGE_INTEGER)Frequency);
     *freq=Frequency.QuadPart;
     QueryPerformanceCounter(&(union _LARGE_INTEGER)TOld);
     *OldTime=TOld.QuadPart;
    }EXPORTFUNC float TestTime(DWORD* NowTime)
    { //DWORD Frequence,old,now;
      float UsedTime;
      QueryPerformanceCounter(&TNow);
      UsedTime=(TNow.QuadPart-TOld.QuadPart)/Frequency.QuadPart;
      return(UsedTime);
    }
    编译通过。我再把TestTime.dll拷贝到D:\TestTime.dll在Delphi里我声明
    implementation
    procedure startcheck(var freq:DWORD;var OldTime:DWORD);external'D:\TestTime.dll';
    function TestTime(var NowTime:DWORD):Real;cdecl;external'TestTime.dll';
    按F9编译又通过!然后在程序里加上
    var
     freq,OldTime,NowTime:DWORD;
    ...
    StartCheck(freq,OldTime);以测量时间
    可再每次按F9运行时总是无法运行(程序刚刚起动就进入单步运行状态)去掉调用就可以了
    大家来帮个忙呀!
      

  7.   

    OK!问题解决了!
    上面缺少一个名为Msvcrtd.dll的文件