关于windows的进程处理(七)

本文介绍了一种利用事件对象进行线程同步的方法。通过创建事件控制并使用SetEvent解除事件阻塞,使得多个线程能够按需启动并执行特定任务。文章提供了具体的代码示例,展示了如何使用事件对象来控制线程的并发执行。

采用事件的方式来通知从线程运行函数退出来,它的实现原理是这样,在那个死循环里不断地使用 WaitForSingleObject函数来检查事件是否满足,如果满足就退出线程,不满足就继续运行。当在线程里运行阻塞的函数时,就需要在退出线程 时,先要把阻塞状态变成非阻塞状态,比如使用一个线程去接收网络数据,同时使用阻塞的SOCKET时,那么要先关闭SOCKET,再发送事件信号,才可以退出线程的。

HANDLE WINAPI CreateEvent(
  _In_opt_ LPSECURITY_ATTRIBUTES lpEventAttributes,
  _In_     BOOL                  bManualReset,
  _In_     BOOL                  bInitialState,
  _In_opt_ LPCTSTR               lpName
);
BOOL WINAPI ResetEvent(
  _In_ HANDLE hEvent
);
BOOL WINAPI SetEvent(
  _In_ HANDLE hEvent
);
BOOL WINAPI CloseHandle(
  _In_ HANDLE hObject
);

CreateEvent的参数:

  • lpEventAttributes:一个指向SECURITY_ATTRIBUTES结构的指针,确定返回的句柄是否可被子进程继承。如果lpEventAttributes是NULL,此句柄不能被继承。
  • bManualReset:指定将事件对象创建成手动复原还是自动复原。如果是TRUE,那么必须用ResetEvent函数来手工将事件的状态复原到无信号状态。如果设置为FALSE,当事件被一个等待线程释放以后,系统将会自动将事件状态复原为无信号状态。
  • bInitialState:指定事件对象的初始状态。如果为TRUE,初始状态为有信号状态;否则为无信号状态。
  • lpName:指定事件的对象的名称,是一个以0结束的字符串指针。名称的字符格式限定在MAX_PATH之内。名字是对大小写敏感的。
#include "stdafx.h"
#include <Windows.h>
#include <process.h>

int num = 0;
CRITICAL_SECTION cs;
HANDLE hEvent = NULL;

unsigned WINAPI ThreadInc(void *arg)
{
	int cnt = *(int*)arg;
	WaitForSingleObject(hEvent, INFINITE);
	for (int i = 0; i < cnt; i++)
	{
		num += 1;
		printf("Inc ");
		Sleep(10);
	}
	return 0;
}
unsigned WINAPI ThreadDec(void *arg)
{
	int cnt = *(int*)arg;
	WaitForSingleObject(hEvent, INFINITE);
	for (int i = 0; i < cnt; i++)
	{
		num -= 1;
		printf("Dec ");
		Sleep(10);
	}
	return 0;
}
int main()
{
	int param = 50;
	HANDLE h[2];
	hEvent = CreateEvent(NULL, true, false, NULL);
	h[0]= (HANDLE)_beginthreadex(NULL, 0, ThreadInc, &param, 0, NULL);
	if (h[0] == 0)
	{
		printf("Can not create a thread 1.\n");
		return 0;
	}
	h[1] = (HANDLE)_beginthreadex(NULL, 0, ThreadDec, &param, 0, NULL);
	if (h[1] == 0)
	{
		printf("Can not create a thread 2.\n");
		return 0;
	}
	printf("Ready to run.\n", num);
	SetEvent(hEvent);
	WaitForMultipleObjects(2, h, true, INFINITE);
	ResetEvent(hEvent);
	CloseHandle(hEvent);

	printf("The num is %d, and end of main.\n", num);
	return 0;
}

上述例子中,主程序中CreateEvent创建了一个事件控制,只有在执行SetEvent后事件阻塞才宣告解除,解除后两个进程就分别开始执行。其执行结果为:

Ready to run.
Inc Dec Inc Dec Inc Dec Inc Dec Dec Inc Dec Inc Inc Dec Inc Dec Dec Inc Inc Dec
Inc Dec Inc Dec Inc Dec Inc Dec Inc Dec Inc Dec Inc Dec Inc Dec Inc Dec Inc Dec
Inc Dec Inc Dec Inc Dec Inc Dec Inc Dec Inc Dec Inc Dec Inc Dec Inc Dec Inc Dec
Inc Dec Inc Dec Inc Dec Inc Dec Inc Dec Inc Dec Inc Dec Inc Dec Inc Dec Inc Dec
Inc Dec Inc Dec Inc Dec Inc Dec Inc Dec Inc Dec Inc Dec Inc Dec Inc Dec Inc Dec
The num is 0, and end of main.

从上面可以看到其执行是在SetEvent后,其执行是独立运行的。

 

转载于:https://my.oschina.net/u/2308182/blog/1421849

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值