http://blog.chinaunix.net/uid-25808509-id-3046252.html
具体的代码和引用的文章一致,这里就对当中一些不懂的地方进行解释和标注。
//myTimer.h #pragma once #ifndef _MY_TIMER_H_ #define _MY_TIMER_H_ #include <Windows.h> class myThread { public: myThread(); virtual ~myThread(); // /* 启动一个定时进程 */ void Start(); /* 停止该定时进程 */ void Stop(); /* 在该定时进程中的定时处理 */ virtual void Run() = 0; /* 封装一个标识,继承的类可以不用对变量进行操作 */ bool IsStop(); protected: /* 线程处理函数 */ static DWORD WINAPI threadProc(LPVOID p); private: /* CreateThread成功会保存一个handle,如果线程结束,用CloseHandle结束 */ HANDLE m_ThreadHandle; bool m_StopFlag; }; class myTimer : public myThread { typedef void(CALLBACK *TimeCallbackFunc)(void *p); typedef TimeCallbackFunc TimeHandle; public: myTimer(void); ~myTimer(void); void RegisteFunc(TimeHandle handle, void *p); void SetInterVal(int millisecond); /* 通过打点计时,超时即处理回调函数 */ void Run(); void Cancel(); private: unsigned int m_InterVal; TimeCallbackFunc m_HandleFuc; void* m_HandleParam; }; #endif //myTimer.cpp #include "myTimer.h" myThread::myThread(void) : m_StopFlag(false), m_ThreadHandle(INVALID_HANDLE_VALUE) { } myThread::~myThread(void) { Stop(); } void myThread::Start() { //传this 指针 -- 是为了在threadProc指针中,对myThread类进行操作 m_ThreadHandle = ::CreateThread(NULL, 0, threadProc, this, 0, NULL); } DWORD WINAPI myThread::threadProc(LPVOID p) { myThread* pThread = (myThread*)p; pThread->Run(); CloseHandle(pThread->m_ThreadHandle); pThread->m_ThreadHandle = INVALID_HANDLE_VALUE; return 0; } void myThread::Stop() { m_StopFlag = true; if (m_ThreadHandle != INVALID_HANDLE_VALUE) { if (WAIT_ABANDONED != WaitForSingleObject(m_ThreadHandle, INFINITE)) { CloseHandle(m_ThreadHandle); } m_ThreadHandle = INVALID_HANDLE_VALUE; } } bool myThread::IsStop() { return m_StopFlag; } myTimer::myTimer(void) : m_InterVal(0), m_HandleFuc(0), m_HandleParam(0) { } myTimer::~myTimer(void) { } void myTimer::RegisteFunc(TimeHandle handle, void *p) { m_HandleFuc = handle; m_HandleParam = p; } void myTimer::SetInterVal(int millisecond) { m_InterVal = millisecond; } void myTimer::Run() { unsigned long m_tickNow = ::GetTickCount(); unsigned long m_tickLast = m_tickNow; while( !IsStop() ) { m_tickNow = ::GetTickCount(); if ( (m_tickNow - m_tickLast) > m_InterVal ) { //回调函数是地址 (*m_HandleFuc)(m_HandleParam); m_tickLast = ::GetTickCount(); } ::Sleep(1); } } void myTimer::Cancel() { Stop(); }1、将定时器通过开辟一个线程来进行操作,这样可以并行运行程序,而不是串行的。
2、传this指针,是在为了在threadProc中,对引用的该线程类进行操作,防止多线程启动时,用了同一个本地变量。
void myThread::Start() { //传this 指针 -- 是为了在threadProc指针中,对myThread类进行操作 m_ThreadHandle = ::CreateThread(NULL, 0, threadProc, this, 0, NULL); }3、这里之所以将线程写成父类,定时器写成子类,是为了在子类中定义回调函数类型,而在父类中定义操作。这样如果回调函数不同,只需重新定义个timer定时器,继承重新run函数即可。
4、CloseHandle对同一个对象不能重复执行,这个跟释放指针是一个道理。释放后,要对handle对象赋值为特定空对象,这个跟指针也是一样的。
5、下面的函数WaitForSingleObject会阻断式等待,直到定时器操作结束,才会执行后续操作,这样就不会出现刚刚启动定时器,就被强制close了。
void myThread::Stop() { m_StopFlag = true; if (m_ThreadHandle != INVALID_HANDLE_VALUE) { if (WAIT_ABANDONED != WaitForSingleObject(m_ThreadHandle, INFINITE)) { CloseHandle(m_ThreadHandle); } m_ThreadHandle = INVALID_HANDLE_VALUE; } }