timeSetEvent timeKillEvent 实现较精确定时

来源:互联网 发布:西安交大网络教育招生 编辑:程序博客网 时间:2024/04/30 14:28
 

1、MOUDLE.abs 文件

  Public lTimeID As Integer
  Public lTimeID2 As Integer

  Public Declare Function QueryPerformanceCounter Lib "kernel32" (lpPerformanceCount As LARGE_INTEGER) As Long
  Public Declare Function QueryPerformanceFrequency Lib "kernel32" (lpFrequency As LARGE_INTEGER) As Long
  Public Declare Function timeSetEvent Lib "winmm.dll" (ByVal uDelay As Long, ByVal uResolution As Long, ByVal lpFunction As Long, ByVal dwUser   As Long, ByVal uFlags As Long) As Long
  Public Declare Function timeKillEvent Lib "winmm.dll" (ByVal uID As Long) As Long
  Public Declare Function GetTickCount Lib "kernel32" () As Long
2、创建定时器
private sub form1_click()
    lTimeID2 = timeSetEvent(1000, 0, AddressOf TimeProcScan, 1, 1)
    If lTimeID2 = 0 Then
        MsgBox "cannot excute timesetevent2"
    End If
    lTimeID = timeSetEvent(100, 0, AddressOf TimeProcAcq, 1, 1)
    If lTimeID = 0 Then
        MsgBox "cannot excute timesetevent"
    End If
end sub
3、定义回调函数(在MOUDLE.ABS中定义) 
Public Function  TimeProcAcq(ByVal uID As Long, ByVal uMsg As Long, ByVal dwUser As Long, ByVal dw1 As Long, ByVal dw2 As Long)
end Function 
Public  Function  TimeProcScan(ByVal uID As Long, ByVal uMsg As Long, ByVal dwUser As Long, ByVal dw1 As Long, ByVal dw2 As Long)
end Function 
4、删除进程(一定要在程序退出之前删除)
Private Sub Form_Unload(Cancel As Integer)
    If lTimeID Then
        timeKillEvent (lTimeID)
    End If
    If lTimeID2 Then
        timeKillEvent (lTimeID2)
    End If
    End
End Sub
5、注:
1 )、timeSetEvent的原形如下:
   MMRESULT timeSetEvent(
   UINT            uDelay,
   UINT            uResolution,
   LPTIMECALLBACK lpTimeProc,
   DWORD_PTR       dwUser,
   UINT            fuEvent
);
uDelay
延时时间
uResolution
误差允许值,如果该值设置为0,则定时器将分毫不差的进行计时,当然,代价是大的开销;一般在程序允许的范围内不妨设置几毫秒的偏差。

LPTIMECALLBACK     是函数指针,指向你的自己的回调函数。
dwUser                        用户自己要传给回调函数的参数。
fuEvent                       说明定时器特性的其他参数,具体如下:
常量                            值                       说明
TIME_ONESHOT                指在预定时间上执行一次,这时就相当于Sleep了一段时间。。
TIME_PERIODIC                周期性执行回调函数。
该函数返回值就是你的timer的标识(uID)
2)、   MMRESULT timeKillEvent(UNIT uID)
    uID是你开始timeSetEvent得到的timer标识(uID)。
注:这个很重要,必须在用完后用该函数杀掉timer,因为这个时钟机制不同于Win32系统API里的时钟设置,它是为了多媒体单独设计的,单独起了一个线程,附加到你的程序进程上。当应用程序退出时,个新的线程不会被正常终止,可能会地址冲突。

 

VC中

在VC编程中,用SetTimer可以定义一个定时器,到时间了,就响应OnTimer消息,但这种定时器精度太低了。如果需要精度更高一些的定时器(精确到1ms),可以使用下面的高精度多媒体定时器进行代码优化,可以达到毫秒级的精度,而且使用方便。先要包含头文件"mmsystem.h"和库文件"winmm.lib"。

源代码
#include "mmsystem.h"  //head file

#pragma comment(lib,"winmm")  //lib file

const    int        timePeriod = 2;
const    int        timeRes = 1 ;




UINT CMyTimer::CreateTimer()
{
    //create the timer
    
    // Create a periodic timer
    timeBeginPeriod(timeRes);
    timerID = timeSetEvent(
        timePeriod,
        timeRes,
        TimerHandler,
        (DWORD)this,
        TIME_PERIODIC);
    
    return timerID;
}


void CMyTimer::DestroyTimer()
{

    if ( bRun )
    {
        timeKillEvent(timerID);
        timeEndPeriod(timeRes);

        bRun = FALSE;
    }


}



void CALLBACK CMyTimer::TimerHandler(UINT id, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2)
{
    CMyTimer* pThis = (CMyTimer*)dwUser;

}



使用多媒体定时器timeSetEvent()函数,该函数定时精度为ms级。利用该函数可以实现周期性的函数调用。函数的原型如下:
       MMRESULT timeSetEvent( UINT uDelay,
                               UINT uResolution,
                               LPTIMECALLBACK lpTimeProc,
                               WORD dwUser,
                               UINT fuEvent )

  该函数设置一个定时回调事件,此事件可以是一个一次性事件或周期性事件。事件一旦被激活,便调用指定的回调函数,成功后返回事件的标识符代码,否则返回NULL。函数的参数说明如下:

       uDelay:以毫秒指定事件的周期。
       Uresolution:以毫秒指定延时的精度,数值越小定时器事件分辨率越高。缺省值为1ms。
       LpTimeProc:指向一个回调函数。
       DwUser:存放用户提供的回调数据。
       FuEvent:指定定时器事件类型:
       TIME_ONESHOT:uDelay毫秒后只产生一次事件
       TIME_PERIODIC :每隔uDelay毫秒周期性地产生事件。

原创粉丝点击