SetTimer与timeSetEvent的应用

一、SetTimer与timeSetEvent的性能区别

SetTimertimeSetEvent是两种不同的定时器方法,它们在精确度、使用场景和功能上有所区别:

‌1)精确度‌:SetTimer的精确度相对较低,它依赖于操作系统的调度和线程切换机制,因此可能存在一定的延迟;imeSetEvent提供了更高的精确度,它是一种精确度非常高的定时器,不使用容易丢失的窗口消息,而是通过回调函数或事件方式触发,提供高的时间控制精度‌;

2‌)使用场景‌:SetTimer适用于简单的定时任务,如周期性地执行某项操作或单次执行某个函数。它通常用于需要定时触发某些事件或操作的场景(如刷新显示界面等)。timeSetEvent则更适合需要极高精度控制的应用场景,如游戏开发中的精确时间控制、科学计算中的精确计时、精确间隔通信等,可以设置定时器的触发时间间隔和使用的分辨率(精确度),并且支持通过回调函数或事件方式进行触发‌;

3)功能特点‌:SetTimer具有较高的灵活性,支持传递额外的参数给要执行的函数,并且可以通过返回的定时器对象进行控制和清除定时器;timeSetEvent则提供了更多的控制选项,包括设置定时器的类型(一次性或周期性触发),并且可以通过timeKillEvent函数来取消定时器。它是微软提供的多媒体定时器API的一部分,用于在非常精确的时间间隔内完成特定事件或函数的调用‌。

总之:SetTimer和timeSetEvent各有其适用场景和优势。SetTimer适合简单的定时任务和需要传递额外参数的场景,而timeSetEvent则提供了更高的精确度和更多的控制选项,适合需要极高精度控制的应用。

二、函数定义及简单应用

本文介绍的用法都是基于MFC的应用。

1、SetTimer

API函数原型:

UINT_PTR SetTimer(
  HWND hWnd,          // 窗口句柄
  UINT_PTR nIDEvent,      // 定时器ID,多个定时器时,可以通过该ID判断是哪个定时器
  UINT uElapse,         // 时间间隔,单位为毫秒
  TIMERPROC lpTimerFunc     // 回调函数
);

例:SetTimer(m_hWnd,1,100,TimerFunc); //一个100ms触发一次的定时器.此处NULL在后面加以说明。

在MFC程序中SetTimer被封装在CWnd类中,调用时不用指定窗口句柄,则SetTimer函数的原型变为: 

UINT SetTimer(

  UINT nIDEvent,

  UINT nElapse,

  void(CALLBACK EXPORT *lpfnTimer)(HWND,UINT ,YINT ,DWORD)

例:SetTimer(2,500,TimerFunc);

该函数通常有两种方式实现:

a) WM_TIMER消息实现:

在MFC例中,第三个参数是一个回调函数,可以设置为NULL,此时使用系统默认的回调函数,系统默认认的是onTime函数.

例:SetTimer(1,1000,NULL);

说明:

1:nIDEvent,计时器名称;

 1000:     时间间隔,单位是毫秒;

   NULL:使用onTime函数  。

onTime函数可以通过添加WM_TIMER消息来生成函数,在MFC中如图所示:

 当不需要计时器的时候调用KillTimer(nIDEvent)来销毁计时器。

BOOL KillTimer(

    HWND hWnd,                  // 窗口句柄,指定要销毁其定时器的窗口

    UINT_PTR uIDEvent        // 要销毁的定时器的标识符

);

例:KillTimer(1);

b) 调用回调函数

回调函数

编程分为两类:系统编程(system programming)和应用编程(application programming)。

  1)系统编程:简单来说,就是编写库;

  2)应用编程:利用写好的各种库来编写具某种功用的程序;

  在抽象层的图示里,库位于应用的底下。当程序跑起来时,一般情况下,应用程序(application program)会时常通过API调用库里所预先备好的函数。但是有些库函数(library function)却要求应用先传给它一个函数,好在合适的时候调用,以完成目标任务。这个被传入的、后又被调用的函数就称为回调函数(callback function)。

例:

SetTimer (hwnd, iTimerID, iMsecInterval, TimerProc) ;

在MFC中,hwnd可省略;

TimerProc为回调函数

void CALLBACK TimerProc(
    HWND hwnd,        // 窗口句柄,接收定时器消息的窗口
    UINT uMsg,        // 消息类型,通常为 WM_TIMER
    UINT_PTR idEvent, // 定时器的标识符,与 SetTimer 中的 nIDEvent 相对应
    DWORD dwTime      // 系统时间,定时器超时时的系统时间
);

回调函数可以是全局的,也可以是静态的。静态的可以在类的头文件中以static +返回类型+ CALLBACK+函数(变量)

用例:

//TimerCallback计时器回调函数,
VOID CALLBACK CXXDlg::TimerCallback(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) 
{
  //GlobalVF::nGPSTime全局变量,GPS通信数据
  
	int year = GlobalVF::nGPSTime.wYear + 2000;
	int month = GlobalVF::nGPSTime.wMonth;
	int day = GlobalVF::nGPSTime.wDay;
	int nh = GlobalVF::nGPSTime.wHour;
	int nm = GlobalVF::nGPSTime.wMinute;
	int ns = GlobalVF::nGPSTime.wSecond;

  GlobalVF::nGPSTime。strTime.Format(_T("%04d.%02d.%02d %02d:%02d:%02d"), year, month,         day, nh, nm, ns);
  
}

 2、timeSetEvent

函数:

MMRESULT timeSetEvent( 

    UINT uDelay,          //以毫秒指定事件的周期

    UINT uResolution,     //以毫秒指定延时的精度, 数值越小定时器事件分辨率越高。缺省值为 
                              //1ms

    LPTIMECALLBACK lpTimeProc,     //指向一个回调函数

    DWORD dwUser,                 //存放用户提供的回调数据

    UINT fuEvent                 //指定定时器事件类型

     ) 

用例:

UINT   nTimeEventID;
DWORD  dwUser;

void CALLBACK TimeProc(UINT nTimeEventID,UINT uMsg,DWORD dwUser,DWORD dw1,DWORD dw2)
{
    int n;
    sockaddr_in RecvAddr;
	RecvAddr.sin_family = AF_INET;
	RecvAddr.sin_port=htons(net_MaincenCopy_IP.RecPort);    //接收数据端口
	RecvAddr.sin_addr.s_addr = htonl(net_MaincenCopy_IP.IP_address);  //接收数据IP地址
    
    //发送数据
    sockaddr_in RecvAddr;
	RecvAddr.sin_family = AF_INET;
	RecvAddr.sin_port=htons(net_MaincenCopy_IP.RecPort);
	RecvAddr.sin_addr.s_addr = htonl(net_MaincenCopy_IP.IP_address);
    n=sendto( cencopy_socket_T,      //SOCKET cencopy_socket_T,需要在程序中进行初始化并设置
				(char*)Cen_MSend,    //BYTE Cen_MSend[100];  //发送信息数组,在程序适当地方 
                                     //付值
				m_dSendN,            //发送字节数
				0,
				(SOCKADDR *) &RecvAddr,    //
				sizeof(RecvAddr));	
     
}

void CXXView::OnInitialUpdate()
{
     .
     .
     .

      nTimeEventID = timeSetEvent(50,1,TimeProc,dwUser,TIME_PERIODIC); //50ms的定时器事件
      
}


//程序退出时注销计时器
void CXXView::OnClose()
{
	// TODO: Add your message handler code here and/or call default
	
	.
    .
    .
	timeKillEvent(nTimeEventID);

	CFormView::OnClose();
}




以上程序可以实现精确间隔时间发送数据,曾在本人某应用程序中用到。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值