基于 TimerQueue 的定时器封装类
本来以为是很简单的事,没想到又牵涉出了线程池,APC,内核定时器对象一大堆没搞明白的知识。先把代码保存下。牵涉到的知识再慢慢消化。
主要使用了以下 API。这些API还是有不少的陷阱(注意点)的,《windows 核心编程》的第11章有详细的解释。
1: CreateTimerQueue
2: DeleteTimerQueueEx
3:
4: CreateTimerQueueTimer
5: DeleteTimerQueueTimer
h文件
1: #pragma once
2:
3:
4: /*
5: * 无窗口的定时器方案
6: */
7:
8: #include "singleton.h"
9:
10: typedef tr1::function<void(DWORD dwID,DWORD dwUserData)> TimerFunObj;
11:
12: class CTimerMgr
13: {
14: public:
15: CTimerMgr(void);
16: ~CTimerMgr(void);
17:
18:
19: public:
20: bool SetTimer(DWORD dwID,DWORD dwElapse,TimerFunObj,DWORD dwUserData);
21: bool KillTimer(DWORD dwID);
22:
23: private:
24:
25: typedef map<DWORD ,HANDLE> MAP_ID_2_HANDLE;
26: MAP_ID_2_HANDLE m_mapTimerID2Handle; //定时器id 映射到定时器的handle
27:
28: HANDLE m_hTimerQueue;
29: };
30:
31: typedef Singleton<CTimerMgr> TimerService;
32:
33: struct TCBParam
34: {
35: CTimerMgr* m_pThis;
36: DWORD m_dwTimerID;
37: TimerFunObj m_func;
38: DWORD m_dwUserData;
39: };
40: extern void _stdcall TimerCBProc(PVOID lpParamter,BOOL TimerorWaitFired);
cpp文件
1: #include "StdAfx.h"
2: #include "TimerMgr.h"
3:
4:
5: CTimerMgr::CTimerMgr(void):m_hTimerQueue(NULL)
6: {
7: m_hTimerQueue = ::CreateTimerQueue();
8: VERIFY(NULL != m_hTimerQueue);
9: }
10:
11:
12: CTimerMgr::~CTimerMgr(void)
13: {
14: if (NULL != m_hTimerQueue)
15: {
16: // INVALID_HANDLE_VALUE:会导致DeleteTimerQueueEx等待所有的timer对应的回调方法完成后再返回
17: DeleteTimerQueueEx(m_hTimerQueue,NULL);
18: }
19: }
20:
21: // dwElapse :milliseconds
22: bool CTimerMgr::SetTimer( DWORD dwID,DWORD dwElapse,TimerFunObj timerfunc,DWORD dwUserData)
23: {
24: VERIFY(NULL != m_hTimerQueue);
25:
26: TCBParam* ptParam = new TCBParam;
27: ptParam->m_pThis = this;
28: ptParam->m_dwTimerID = dwID;
29: ptParam->m_func = timerfunc;
30: ptParam->m_dwUserData = dwUserData;
31:
32: HANDLE hTimer = NULL;
33: if( 0 != CreateTimerQueueTimer(&hTimer,m_hTimerQueue,(WAITORTIMERCALLBACK)TimerCBProc,(void*)ptParam,dwElapse,0,WT_EXECUTEDEFAULT))
34: {
35: m_mapTimerID2Handle[dwID] = hTimer;
36: return true;
37: }
38: else //失败
39: {
40: delete ptParam;
41: ptParam = NULL;
42: return false;
43: }
44:
45: }
46:
47: bool CTimerMgr::KillTimer( DWORD dwID )
48: {
49: MAP_ID_2_HANDLE::iterator it = m_mapTimerID2Handle.find(dwID);
50:
51: if (it == m_mapTimerID2Handle.end())//不存在
52: return false;
53:
54: HANDLE hTimer = it->second;
55: BOOL bSuc = ( 0 != ::DeleteTimerQueueTimer(m_hTimerQueue,hTimer,NULL) );
56:
57: if (bSuc )
58: {
59: m_mapTimerID2Handle.erase(it);
60: return true;
61: }
62: //之前定义的处理函数即将被调用或正在被调用,立刻返回,但系统会在处理函数调用完成后自动删除这个定时器
63: else if (ERROR_IO_PENDING == GetLastError())
64: {
65: m_mapTimerID2Handle.erase(it);
66: return true;
67: }
68: else
69: {
70: return false;
71: }
72:
73:
74:
75:
76: }
77:
78:
79: void _stdcall TimerCBProc( PVOID lpParamter,BOOL TimerorWaitFired )
80: {
81: TCBParam* ptParam = (TCBParam*)lpParamter;
82: if (NULL == ptParam)
83: return;
84: CTimerMgr* pThis = ptParam->m_pThis;
85: DWORD dwTimerID = ptParam->m_dwTimerID;
86: TimerFunObj funcTimer = ptParam->m_func;
87: DWORD dwUserData = ptParam->m_dwUserData;
88:
89: funcTimer(dwTimerID,dwUserData);
90:
91: delete ptParam;
92: ptParam = NULL;
93: }
调用代码:
1: class CInvoker
2: {
3: public:
4: void TimerProc(DWORD dwID,DWORD dwUserData )
5: {
6: //...
7: }
8: }
9:
10: CInvoker _invoker;
11: TimerFunObj proc = tr1::bind(&CInvoker::TimerProc,&_invoker,tr1::placeholders::_1,tr1::placeholders::_2);