【C语言】Windows下的多线程编程-事件

事件Event上是个内核对象,它的使用非常方便。下面列出一些常用的函数。

CreateEvent创建事件

/** \brief 	创建事件
 *
 * \param   lpEventAttributes 表示安全控制,一般直接传入NULL
 * \param   bManualReset 确定事件是手动置位还是自动置位,传入TRUE表示手动置位,传入FALSE表示自动置位。
 *				如果为自动置位,则对该事件调用WaitForSingleObject()后会自动调用ResetEvent()使事件变成未触发状态。
 * \param   bInitialState 表示事件的初始状态,传入TRUR表示已触发
 * \param   lpName 表示事件的名称,是一个以0结束的字符串指针。名称的字符格式限定在MAX_PATH之内。
 *				名字是对大小写敏感的。传入NULL表示匿名事件
 * \return  成功,函数返回事件对象的句柄。如果对于命名的对象,在函数调用前已经被创建,函数将返回存在的事件对象的句柄,
 *			而且在GetLastError函数中返回ERROR_ALREADY_EXISTS。
 *			失败,函数返回值为NULL,如果需要获得详细的错误信息,需要调用GetLastError
 *
 */
HANDLE CreateEvent(
	LPSECURITY_ATTRIBUTES lpEventAttributes,
	BOOL bManualReset,
	BOOL bInitialState,
	LPCTSTR lpName
);

其中HANDLE是空指针类型。

OpenEvent返回事件对象的句柄

/** \brief 	返回事件对象的句柄
 *
 * \param   dwDesiredAccess 表示访问权限,对事件一般传入EVENT_ALL_ACCESS。
 * \param   bInheritHandle 事件句柄继承性。
 * \param   lpName 表示事件的名称,是一个以0结束的字符串指针。名称的字符格式限定在MAX_PATH之内。
 *				名字是对大小写敏感的。
 * \return  成功则返回事件对象的句柄;失败则返回NULL,获取错误信息可以使用GetLastError
 *
 */
HANDLE OpenEvent(
	DWORD dwDesiredAccess,
	BOOL bInheritHandle,
	LPCTSTR lpName
);

SetEvent触发事件

/** \brief 	触发事件
 *				每次触发后,必有一个或多个处于等待状态下的线程变成可调度状态 
 *
 * \param   hEvent 要触发的事件的句柄(内核对象)
 * \return  成功,则返回非零值,否则为0。
 *
 */
BOOL SetEvent(HANDLE hEvent);

ResetEvent将事件设为未触发

/** \brief 	将事件设为未触发
 *
 * \param   hEvent 指向事件对象的句柄,这个句柄需要拥有EVENT_MODIFY_STATE 访问权限
 * \return  成功,返回非0值,否则返回0值,可以调用GetLastError得到错误的详细信息
 *
 */
BOOL ResetEvent(HANDLE hEvent);

CloseHandle销毁

由于事件是内核对象,因此使用CloseHandle()就可以完成清理与销毁了。

/** \brief 	关闭一个内核对象
 *
 * \param   hObject 代表一个已打开对象handle。
 * \return  TRUE:执行成功;FALSE:执行失败,可以调用GetLastError()获知失败原因。
 *
 */
BOOL CloseHandle(HANDLE hObject);

示例

主线程与2个子线程依次执行

#include <stdio.h>
#include <Windows.h>
#include <process.h>


void Thread1(void*);
void Thread2(void*);


volatile int count = 0;

HANDLE th1, th2;//线程句柄
unsigned long th1ID, th2ID;//线程ID
HANDLE e1, e2, e3;//事件句柄


int main()
{
	/* 创建事件 */
	//自动置位,初始化无触发的事件
	e1 = CreateEvent(NULL, FALSE, FALSE, "e1");
	e2 = CreateEvent(NULL, FALSE, FALSE, "e2");
	e3 = CreateEvent(NULL, FALSE, FALSE, "e3");

	/* 创建线程 */
	th1 = _beginthread(Thread1, 0, NULL);
	th2 = _beginthread(Thread2, 0, NULL);

	/* 获取线程ID */
	th1ID = GetThreadId(th1);
	th2ID = GetThreadId(th2);


	while (1)
	{
		Sleep(200);
		printf("主线程\n");
		SetEvent(e1);//触发事件1
		WaitForSingleObject(e3, INFINITE);//等待事件3
	}

	/* 等待线程结束 */
	WaitForSingleObject(th1, INFINITE);
	
	/* 销毁事件 */
	CloseHandle(e1);
	CloseHandle(e2);
	CloseHandle(e3);

	return 0;
}


void Thread1(void* arg)
{
	while (1)
	{
		WaitForSingleObject(e1, INFINITE);//等待事件1
		//ResetEvent(e1);//如果事件是手动置位,则需要调用该函数给事件设置为未触发状态
		count += 1;
		printf("线程1  当前count的值为:%d\n", count);
		SetEvent(e2, INFINITE);//触发事件2
	}
}


void Thread2(void* arg)
{
	while (1)
	{
		WaitForSingleObject(e2, INFINITE);//等待事件2
		count += 50;
		printf("线程2  当前count的值为:%d\n", count);
		SetEvent(e3, INFINITE);//触发事件3
	}
}

输出结果
在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值