自护意识

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

平时创建定时器使用的是WINAPI  SetTimer,不过该函数一般用于有界面的时候。无界面的情况下,可以选择微软提供的CreateWaitableTimer和SetWaitableTimer API。

 

HANDLE WINAPI CreateWaitableTimer(
  _In_opt_  LPSECURITY_ATTRIBUTES lpTimerAttributes,
  _In_      BOOL bManualReset,
  _In_opt_  LPCTSTR lpTimerName
);

BOOL WINAPI SetWaitableTimer(
  _In_      HANDLE hTimer,
  _In_      const LARGE_INTEGER *pDueTime,
  _In_      LONG lPeriod,
  _In_opt_  PTIMERAPCROUTINE pfnCompletionRoutine,
  _In_opt_  LPVOID lpArgToCompletionRoutine,
  _In_      BOOL fResume
);

详细介绍可以查看MSDN( http://msdn.microsoft.com/en-us/library/windows/desktop/ms682492(v=vs.85).aspx )

一、应用实例

我自己在使用的时候,封装了一个类,用来创建了一个线程,并定时调用我提供的函数。类代码如下:

 1 #ifndef APLAYER_TIMERTHREAD_H
 2 #define APLAYER_TIMERTHREAD_H
 3 #include <Windows.h>
 4 class CTimerThread
 5 {
 6 public:
 7     CTimerThread() :
 8         _hThread(NULL), _hEvent(NULL),
 9         _bRunning(false), _nInterval(10)
10     {}
11     ~CTimerThread()
12     {
13         KillTimer();
14     }
15 public:
16     int                        CreateTimer(unsigned int interval, PTIMERAPCROUTINE func, void* lpParam);
17     void                    KillTimer();
18 private:
19     static DWORD WINAPI        timerThread(LPVOID lpParam);
20 
21 private:
22     HANDLE                _hTimer;
23     int                    _nInterval;
24     HANDLE                _hEvent;
25     void*                _lpParam;
26 
27     PTIMERAPCROUTINE    _callbackFunc;
28     HANDLE                _hThread;
29     DWORD                _dwThread;
30     bool                _bRunning;
31 };
32 
33 #endif
TimerThread.h
 1 #include "TimerThread.h"
 2 
 3 void CTimerThread::KillTimer()
 4 {
 5     if (_hTimer != NULL) {
 6         CancelWaitableTimer(_hTimer);
 7         CloseHandle(_hTimer);
 8         _hTimer = NULL;
 9     }
10     _bRunning = false;
11 }
12 int CTimerThread::CreateTimer(unsigned int interval, PTIMERAPCROUTINE func, void* lpParam)
13 {
14     if (_bRunning) return TRUE;
15     _nInterval = interval;
16     _callbackFunc = func;
17     _lpParam = lpParam;
18     _bRunning = true;
19     _hThread = CreateThread(
20         NULL,
21         0,
22         timerThread,
23         this,
24         0,
25         &_dwThread
26         );
27     if (_hThread == NULL) {
28         _bRunning = false;
29         return FALSE;
30     }
31     CloseHandle(_hThread);
32     return TRUE;
33 }
34 
35 DWORD CTimerThread::timerThread(LPVOID lpParam)
36 {
37     CTimerThread* pThis = (CTimerThread*)lpParam;
38     do {
39         pThis->_hTimer = CreateWaitableTimer(NULL, FALSE, NULL);
40         if (pThis->_hTimer == NULL) break;
41 
42         LARGE_INTEGER liDueTime;
43         liDueTime.QuadPart = 0;
44         BOOL bRet = SetWaitableTimer(
45             pThis->_hTimer,
46             &liDueTime,
47             pThis->_nInterval,
48             pThis->_callbackFunc,
49             pThis->_lpParam,
50             FALSE);
51         do {
52             SleepEx(30000, TRUE);
53         } while (pThis->_bRunning);
54         return bRet;
55     } while (0);
56     return 0;
57 }
TimerThread.cpp

TimerThread.h/cpp实现了一个可以定时调用函数的类。使用的时候也很简单。首先定义一个要被调用的函数

void __stdcall DoSomething(void *lpParam, DWORD, DWORD)
{
  //to do
}
void *lpParam;
CTimerThread _timer;
_timer.CreateTimer(50, DoSomething, lpParam);
//
some code
....
//
_timer.KillTimer();

DoSomething函数在_timer.CreateTimer 和_timer.KillTimer之间会每隔50ms调用一次。

二、详细说明

下面根据我自己的理解介绍下这两个函数。

1.CreateWaitableTimer

1 HANDLE WINAPI CreateWaitableTimer(
2   _In_opt_  LPSECURITY_ATTRIBUTES lpTimerAttributes,
3   _In_      BOOL bManualReset,
4   _In_opt_  LPCTSTR lpTimerName
5 );


用来创建一个timer对象。首先翻译下MSDN对各参数的介绍(个人理解):

lpTimerAttributes 

 略过,具体可以查看MSDN或《Windows核心编程》,一般设置为NULL。

bManualReset  

If this parameter is TRUE, the timer is a manual-reset notification timer. Otherwise, the timer is a synchronization timer.

(此处不知道如何翻译才能清晰的传达意思,故抄录原文。用我的语言解释就是,如果为TRUE,则该timer到时间时,需要手动重置才能有下一次;FALSE则每次到时后自动进行下一次计时)

lpTimerName 

该timer对象的名称。最大MAX_PATH个字母,区分大小写。

传递NULL则创建一个没有名字的timer对象。

如果名称和现有的event,semaphore,mutex,job or file-mapping对象名称冲突,则该函数失败,调用GetLastError会返回ERROR_INVALID_HANDLE错误。原因是这些对象共享相同的命名空间。

返回值(return value)

如果函数调用成功,则返回指向timer对象的handle。如果和现有的已命名timer同名,则返回指向该timer的handle。

2.SetWaitableTimer

1 BOOL WINAPI SetWaitableTimer(
2   _In_      HANDLE hTimer,
3   _In_      const LARGE_INTEGER *pDueTime,
4   _In_      LONG lPeriod,
5   _In_opt_  PTIMERAPCROUTINE pfnCompletionRoutine,
6   _In_opt_  LPVOID lpArgToCompletionRoutine,
7   _In_      BOOL fResume
8 );

启动timer对象。首先翻译下MSDN对各参数的介绍(个人理解):

hTimer

指向timer对象的handle。显然可以是CreateWaitableTimer函数返回的handle。

pDueTime

该时间之后的timer会signaled(意会下..),间隔为100纳秒(应该就是此值的单位吧?)

正值的话,就是基于UTC的绝对时间。负值的话就是相对现在的时间了。

例如-10 000 000表示1s后。

lPeriod

嗯,这个就是我比较关心的参数,signaled间隔。类似于SetTimer里那个间隔。单位毫秒(ms)

为0则只signaled一次。

pfnCompletionRoutine


每次signaled都会调用此处的函数了,传递一个函数指针。原型为:

typedef
VOID
(APIENTRY *PTIMERAPCROUTINE)(
    _In_opt_ LPVOID lpArgToCompletionRoutine,  \\SetWaitableTimer传入的参数lpArgToCompletionRoutine
    _In_     DWORD dwTimerLowValue,
    _In_     DWORD dwTimerHighValue
    );

 

lpArgToCompletionRoutine

传入的参数,往上看:-)

fResume

懒得介绍,自己看msdn,一般设置为FALSE。

返回值(return value)

成功返回非零值。

posted on 2014-02-08 08:55  自护意识  阅读(9796)  评论(0编辑  收藏  举报