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;
}
}