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

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值