游戏编程学习笔记01 -- 定时器操作

来源:互联网 发布:linux中telnet命令 编辑:程序博客网 时间:2024/05/17 02:59

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