要包含<windows.h>文件
CreateEvent
该函数创建一个事件对象,如果创建成功,会返回新生成的对象的句柄,否则返回NULL。
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes,// 安全属性
BOOL bManualReset, // 复位方式
BOOL bInitialState,// 初始状态
LPCTSTR lpName // 对象名称
);
lpEventAttributes: 确定返回的句柄是否可被子进程继承。如果lpEventAttributes是NULL,此句柄不能被继承。一般都设置为NULL。
bManualReset: 事件信号的复位方式,true-->人工复位,false-->自动复位。人工复位时,如果该Event被设置为有信号,则它一直会等到ResetEvent() API被调用时才会恢复为无信号。自动复位时,如果Event被设置为有信号,则当有一个wait到它的Thread时,该Event就会自动恢复为无信号。如果想在每次调用WaitForSingleObject 后让WINDOWS为你自动地把事件的状态恢复为”无信号”状态,必须把该参数设为FALSE,否则您必须每次调用ResetEvent函数来清除事件的信号。
bInitialState: 指定事件对象的初始状态。如果为true,初始状态为有信号状态,否则为无信号状态。
lpName: 改事件对象的名称,在OpenEvent 函数中可能使用。如果lpName为NULL,将创建一个无名的事件对象。
SetEvent
将指定的事件设置为有信号状态。如果操作成功,则返回非0值,否则为0。
BOOL SetEvent(HANDLE hEvent);
ResetEvent
将指定的事件设置为无信号状态。函数成功,返回非0值,否则返回0值,可以调用GetLastError得到错误的详细信息。
BOOL ResetEvent(HANDLE hEvent);
OpenEvent
打开一个已经存在的有命名事件对象,函数执行成功则返回事件对象的句柄,失败则返回NULL,获取错误信息可以使用GetLastError。
HANDLE OpenEvent(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
LPCTSTR lpName
);
dwDesiredAccess:
指定对事件对象的请求访问权限,参数必须设置为EVENT_ALL_ACCESS(指定事件对象所有可能的权限)
bInheritHandle: 指定是否返回的句柄是否继承,该参数必须设置为false。
lpName: 要打开的事件对象的名字,名称是区分大小写的。
CloseHandle
关闭一个已打开的对象,可以是事件或线程等。执行成功返回true,失败返回false。
BOOL CloseHandle(HANDLE hObject);
CreateThread
用于在主线程的基础上创建一个新线程,成功则返回线程句柄,失败返回NULL。
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, //SD
SIZE_T dwStackSize, //initialstacksize
LPTHREAD_START_ROUTINE lpStartAddress, //threadfunction
LPVOID lpParameter, //threadargument
DWORD dwCreationFlags, //creationoption
LPDWORD lpThreadId //threadidentifier
)
lpThreadAttributes: 第一个参数是指向SECURITY_ATTRIBUTES型态的结构的指针,通常设置为NULL。
dwStackSize: 用于新线程的初始堆栈大小,默认值为0。在任何情况下,Windows根据需要动态延长堆栈的大小。
lpStartAddress: 线程函数指针。函数名称没有限制,但是必须以DWORD WINAPI ThreadProc (void* pParam)形式声明。
lpParameter: 传递给ThreadProc线程函数的参数。这样主线程和从属线程就可以共享数据。
dwCreationFlags: 通常为0,表示创建后立即激活线程。但当建立的线程不马上执行时应设为CREATE_SUSPENDED,线程将暂停直到呼叫ResumeThread来恢复线程的执行为止。
lpThreadId: 新线程的ID号。
TerminateThread
在线程外终止一个线程,用于强制终止线程。函数执行成功则返回非0值,执行失败返回0。调用getlasterror获得返回的值。
BOOL TerminateThread( HANDLE hThread,DWORD dwExitCode);
hThread: 要终止的线程的句柄。
dwExitCode: 线程的退出值。
SetThreadPriority
设置线程的优先级,线程的优先级和进程的优先级组合在一起就决定了线程的实际优先级
BOOL SetThreadPriority(
HANDLE hThread, // handle to the thread
int nPriority // thread priority level
);
优先级参数:
WaitForSingleObject
该函数用来,检测hHandle事件的信号状态,在某一线程中调用该函数时,线程暂时挂起,如果在挂起的dwMilliseconds毫秒内,线程所等待的对象变为有信号状态,则该函数立即返回。如果超时时间已经到达dwMilliseconds毫秒,但hHandle所指向的对象还没有变成有信号状态,函数照样返回。该函数可用于等待某个线程关闭。
DWORD WaitForSingleObject(
HANDLE hHandle, //对象句柄
DWORD dwMilliseconds //超时时间
);
hHandle: 对象句柄。可以指定一系列的对象,如Event、Job、Memory resource notification、Mutex、Process、Semaphore、Thread、Waitable timer等。
dwMilliseconds: 参数dwMilliseconds有两个具有特殊意义的值:0和INFINITE。若为0,则该函数立即返回。若为INFINITE,则线程一直被挂起,直到hHandle所指向的对象变为有信号状态时为止。
返回值:返回WAIT_TIMEOUT表示等待超时。返回WAIT_OBJECT_0表示指定的对象有信号了。返回WAIT_FAILED表示出现错误,可通过GetLastError得到错误代码。WaitForMultipleObjects
WaitForMultipleObjects是Windows中的一个功能非常强大的函数,几乎可以等待Windows中的所有的内核对象。
DWORD WaitForMultipleObjects(
DWORD nCount, // number of handles in the handle array
const HANDLE* lpHandles, // pointer to the object-handle array
BOOL bWaitAll, // wait flag
DWORD dwMilliseconds // time-out interval in milliseconds
);
nCount: 要等待的
事件的数量。
lpHandles: 事件句柄数组的指针(将所有需要的事件句柄放入一个HANDLE类型数组中)。
bWaitAll: 等待的类型,如果为TRUE 则等待所有信号量有效在往下执行,FALSE 当有其中一个信号量有效时就向下执行。
dwMilliseconds: 超时时间,超时后向下执行。如果为INFINITE,则没有等到事件就会在这死等。
返回值:当bWaitAll为false时,则返回值WAIT_OBJECT_0到WAIT_OBJECT_0 + nCount - 1之间的值。 返回值减去WAIT_OBJECT_0后的值,表示lpHandles数组中哪个事件处于有信号状态,如果同时有多个事件处于有信号状态,则返回索引值最小的事件的值。如果返回WAIT_TIMEOUT,表示等待超时了。
用多线程实现定时器
//TimerImp.h
#ifndef __TIMERIMP_H_
#define __TIMERIMP_H_
class CTimerImp
{
public:
CTimerImp(void (*TimerProc)(void))
:m_hStopTimer(0)
,m_hStartTimer(0)
,m_hQuitThread(0)
,m_dTimerThreadID(0)
,m_bInitialized(false)
,m_hTimerThread(NULL)
,m_bRepeative(false)
,m_dPeriod(0)
{
//初始化函数指针
OnTimer = TimerProc;
}
void Initialize();
bool StartTimer(DWORD dPeriod, bool bRepeative = true);
void StopTimer();
//也可以将OnTimer声明为纯虚函数,在派生类中根据实际需要
//重新定义OnTimer函数体
//void OnTimer();
~CTimerImp()
{
RequestTimerThreadQuit(1000,true);
if (m_bInitialized)
{
//关闭所有事件和线程句柄
CloseHandle(m_hStopTimer);
CloseHandle(m_hStartTimer);
CloseHandle(m_hQuitThread);
CloseHandle(m_hTimerThread);
}
m_hStopTimer = 0;
m_hStartTimer = 0;
m_hQuitThread = 0;
m_hTimerThread = 0;
m_dTimerThreadID = 0;
m_bRepeative = false;
m_dPeriod = 0;
m_bInitialized = false;
}
protected:
//在定时器对象销毁前,要先关闭定时器线程,确保安全
bool RequestTimerThreadQuit(DWORD dwWaitThreadQuit, bool bTerminateThread);
private:
HANDLE m_hStopTimer; //停止定时事件
HANDLE m_hStartTimer; //开始定时事件
HANDLE m_hQuitThread; //关闭线程事件
HANDLE m_hTimerThread; //定时器线程
DWORD m_dTimerThreadID;
bool m_bInitialized;
DWORD m_dPeriod; //定时器定时时间
bool m_bRepeative; //是否重复定时
void (*OnTimer)(void); //定时时间到后,要调用的函数
//定时器线程函数,类中包含的线程函数必须是static的
static DWORD WINAPI TimerThreadProc(void * pParam);
};
#endif
//TimerImp.cpp
//#include <windows.h>语句在stdafx.h文件中
#include "stdafx.h"
#include "TimerImp.h"
void CTimerImp::Initialize()
{
//创建事件和定时器线程
m_hStopTimer = CreateEvent(NULL, false, false, NULL);
m_hStartTimer = CreateEvent(NULL, false, false, NULL);
m_hQuitThread = CreateEvent(NULL, false, false, NULL);
m_hTimerThread = CreateThread(NULL, 0, TimerThreadProc, this, 0, &m_dTimerThreadID);
m_bInitialized = true;
}
bool CTimerImp::StartTimer(DWORD dPeriod, bool bRepeative)
{
if (!m_bInitialized)
Initialize();
if (m_hTimerThread == NULL)
return false;//创建线程失败,直接返回
SetEvent(m_hStopTimer);
m_dPeriod = dPeriod;
m_bRepeative = bRepeative;
SetEvent(m_hStartTimer);
return true;
}
void CTimerImp::StopTimer()
{
if (m_hTimerThread == NULL)
return;
SetEvent(m_hStopTimer);
}
bool CTimerImp::RequestTimerThreadQuit(DWORD dwWaitThreadQuit, bool bTerminateThread)
{
bool bWaitSucceed = true;
if (m_bInitialized)
{
SetEvent(m_hQuitThread);
//用WaitForSingleObject等待定时器线程关闭,如果返回WAIT_OBJECT_0,则表示线程关闭了
if (WAIT_OBJECT_0 != WaitForSingleObject(m_hTimerThread, dwWaitThreadQuit))
{
if (bTerminateThread)
{
//线程没有退出成功,强制关闭线程
TerminateThread(m_hTimerThread, 1);
}
bWaitSucceed = false;
}
}
return bWaitSucceed;
}
DWORD WINAPI CTimerImp::TimerThreadProc(void * pParam)
{
CTimerImp * pTimer = (CTimerImp *)pParam;//定时器对象指针
//要等待的事件的数组
const HANDLE vEventHandler[] =
{
pTimer->m_hStopTimer,
pTimer->m_hStartTimer,
pTimer->m_hQuitThread
};
const int icStopTimer = WAIT_OBJECT_0;
const int icStartTimer = WAIT_OBJECT_0 + 1;
const int icQuitThread = WAIT_OBJECT_0 + 2;
int iEventCount = sizeof(vEventHandler)/sizeof(vEventHandler[0]);//事件数目
bool bRepeative = pTimer->m_bRepeative;
DWORD dTimeout = INFINITE;
bool bQuit = false;
while(!bQuit)
{
int iEventNum = WaitForMultipleObjects(iEventCount, vEventHandler, false, dTimeout);
//int ierror = GetLastError();//获取最后一次出错信息
switch(iEventNum)
{
case icStopTimer:
dTimeout = INFINITE;//无限等待,就等于是关闭定时器
break;
case icStartTimer:
dTimeout = pTimer->m_dPeriod;
bRepeative = pTimer->m_bRepeative;
break;
case icQuitThread:
bQuit = true;//关闭定时器线程
break;
case WAIT_TIMEOUT:
pTimer->OnTimer();//调用函数
if (!bRepeative)
{
//如果只定时一次的话,就关闭定时器
dTimeout = INFINITE;
}
break;
default:
break;
}
}
return 0;
}
使用定时器
#include "stdafx.h"
#include <iostream>
#include "TimerImp.h"
using namespace std;
//根据实际情况,定义一个函数,定时时间到后会调用这个函数
void OnTiemr()
{
cout<<"time out"<<endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
CTimerImp myTimer(OnTiemr);
myTimer.StartTimer(400, true);
while(1);
return 0;
}