windows下C++多线程

要包含<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_0WAIT_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;
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值