c++中SetEvent和ResetEvent的使用
关于事件
事件(Event)是WIN32提供的最灵活的线程间同步方式,事件可以处于激发状态(signaled or true)或未激发状态(unsignal or false)。根据状态变迁方式的不同,事件可分为两类:
(1)手动设置:这种对象只可能用程序手动设置,在需要该事件或者事件发生时,采用SetEvent及ResetEvent来进行设置。
(2)自动恢复:一旦事件发生并被处理后,自动恢复到没有事件状态,不需要再次设置。
创建事件的函数原型为:
HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes,
// SECURITY_ATTRIBUTES结构指针,可为NULL
BOOL bManualReset,
// 手动/自动
// TRUE:在WaitForSingleObject后必须手动调用ResetEvent清除信号
// FALSE:在WaitForSingleObject后,系统自动清除事件信号
BOOL bInitialState, //初始状态
LPCTSTR lpName //事件的名称
);
使用"事件"机制应注意以下事项:
(1)如果跨进程访问事件,必须对事件命名,在对事件命名的时候,要注意不要与系统命名空间中的其它全局命名对象冲突;
(2)事件是否要自动恢复;
(3)事件的初始状态设置。
看下面代码:
// event.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <wtypes.h>
#include <iostream>
using namespace std; DWORD WINAPI ThreadProc(LPVOID lpParam);
DWORD WINAPI ThreadProc2(LPVOID lpParam); DWORD g_dwThreadID;
DWORD g_dwThreadID2; UINT g_nTickets = ; //int g_nTickets = 300; //备注1 HANDLE g_hEvent1 = NULL;
HANDLE g_hEvent2 = NULL; CRITICAL_SECTION g_cs; int ThreadCout = ; int _tmain(int argc, _TCHAR* argv[])
{
cout << "Main thread is running." << endl; InitializeCriticalSection(&g_cs);//初始化临界区 HANDLE hHandle = CreateThread(NULL, , ThreadProc, NULL, , &g_dwThreadID);
ThreadCout++;
HANDLE hHandle2 = CreateThread(NULL, , ThreadProc2, NULL, , &g_dwThreadID2);
ThreadCout++; g_hEvent1 = CreateEvent(NULL, FALSE, TRUE, NULL); //备注5:g_hEvent1 = CreateEvent(NULL, TRUE, TRUE, NULL);
g_hEvent2 = CreateEvent(NULL, FALSE, TRUE, NULL); //备注5:g_hEvent2 = CreateEvent(NULL, TRUE, TRUE, NULL); ResetEvent(g_hEvent1);
ResetEvent(g_hEvent2); SetEvent(g_hEvent1); while (TRUE)
{
EnterCriticalSection(&g_cs);
int nCount = ThreadCout;
LeaveCriticalSection(&g_cs); if (nCount == )
{
cout << "Main thread is break." << endl;
break;
} } Sleep(); //备注4 CloseHandle(hHandle);
CloseHandle(hHandle2); DeleteCriticalSection(&g_cs); cout << "Main thread is end." << endl; system("pause");
return ;
} DWORD WINAPI ThreadProc(LPVOID lpParam)
{
// cout << "No." << g_dwThreadID << " thread is running." << endl;
while (TRUE)
{
WaitForSingleObject(g_hEvent1, INFINITE);
cout << "No.1 " << g_dwThreadID << " thread is running." << endl; EnterCriticalSection(&g_cs);
int temp = g_nTickets;
LeaveCriticalSection(&g_cs); cout << "No.1 " << g_dwThreadID << " thread is temp." << endl; if (temp > )
{
Sleep(); //Sleep(1000) //备注2
cout << "No.1-" << g_dwThreadID << " sell ticket : " << temp << endl; EnterCriticalSection(&g_cs);
g_nTickets--;
LeaveCriticalSection(&g_cs); SetEvent(g_hEvent2);
//ResetEvent(g_hEvent1);//备注6
}
else
{
cout << "No.1- break" << endl;
//ResetEvent(g_hEvent1);//备注6
SetEvent(g_hEvent2);//没有这个ThreadProc2不能终止 //备注3
break;
}
} EnterCriticalSection(&g_cs);
ThreadCout--;
LeaveCriticalSection(&g_cs);
cout << "No.1- end" << endl; return ;
} DWORD WINAPI ThreadProc2(LPVOID lpParam)
{
//
while (TRUE)
{
WaitForSingleObject(g_hEvent2, INFINITE);
cout << "No.2 " << g_dwThreadID2 << " thread is running." << endl; EnterCriticalSection(&g_cs);
int temp = g_nTickets;
LeaveCriticalSection(&g_cs); if (temp > )
{
Sleep(); //Sleep(1000) //备注2
cout << "No.2-" << g_dwThreadID2 << " sell ticket : " << temp << endl; EnterCriticalSection(&g_cs);
g_nTickets--;
LeaveCriticalSection(&g_cs); SetEvent(g_hEvent1);
//ResetEvent(g_hEvent2);//备注6
}
else
{
cout << "No.2- break" << endl;
//ResetEvent(g_hEvent2);//备注6
SetEvent(g_hEvent1);//同样的问题,没有这个ThreadProc不能终止 //备注3
break;
}
} EnterCriticalSection(&g_cs);
ThreadCout--;
LeaveCriticalSection(&g_cs); cout << "No.2- end" << endl;
return ;
}
这个代码是接上一遍关于UINT类型作为循环变量的不确定性问题继续完善的,加入了临界区控制全局变量的访问。
本文要说明的是SetEvent和ResetEvent的使用,这个要看备注5和备注6。
备注5处:
CreateEvent的第二个参数决定了是否需要手动调用ResetEvent,当为TRUE时,是需要手动调用,如果不调用,会怎么样呢?不调用,事件会处于一直有信号状态,即备注6处。当为FALSE时候,不需要手动调用,调用不调用,效果一样。把ResetEvent放在WaitForSingleObject前面也是很好的做法。
转载请注明原创链接:http://blog.csdn.net/wujunokay/article/details/12272581
c++中SetEvent和ResetEvent的使用的更多相关文章
- CreateEvent、SetEvent、ResetEvent和WaitForSingleObject
事件对象就像一个开关:它仅仅有两种状态---开和关.当一个事件处于"开"状态.我们称其为"有信号".否则称为"无信号". 能够在一个线程的运 ...
- Delphi中线程类TThread实现多线程编程2---事件、临界区、Synchronize、WaitFor……
接着上文介绍TThread. 现在开始说明 Synchronize和WaitFor 但是在介绍这两个函数之前,需要先介绍另外两个线程同步技术:事件和临界区 事件(Event) 事件(Event)与De ...
- 转发 Delphi中线程类TThread 实现多线程编程
Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大多数Delphi书藉都有说到,但基本上都是对TThread类的几个成员作一简单介绍,再说明一下Execute的实现和Synchr ...
- MFC中线程相关知识
MFC中把线程分为两种类型,UI线程和工作者线程. MFC中启动一个线程的最好方法是调用AfxBeginThread,有两个版本,一个用于启动Ui线程,另外一个用于启动工作者线程.在MFC程序中,只有 ...
- Delphi中的线程类 - TThread详解
Delphi中的线程类 - TThread详解 2011年06月27日 星期一 20:28 Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大多数Delphi书藉都有说到,但基本 ...
- Delphi中的线程类(转)
Delphi中的线程类 (转) Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大多数Delphi书藉都有说到,但基本上都是对 TThread类的几个成员作一简单介绍,再说明一下 ...
- c++中CreateEvent函数
参考:https://blog.csdn.net/u011642774/article/details/52789969 函数原型: HANDLE CreateEvent( LPSECURITY_AT ...
- SETEVENT的使用
来源:https://msdn.microsoft.com/en-us/library/windows/desktop/ms686915(v=vs.85).aspx 昨天看到这个SetEvent的方法 ...
- windows核心编程 - 线程同步机制
线程同步机制 常用的线程同步机制有很多种,主要分为用户模式和内核对象两类:其中 用户模式包括:原子操作.关键代码段 内核对象包括:时间内核对象(Event).等待定时器内核对象(WaitableTim ...
随机推荐
- Clion调试ROS包
1. 安装 从官网下载最新版本的Clion https://www.jetbrains.com/clion/ 并解压到指定的目录,例如: /home/xkc/software/clion-2017.2 ...
- java三大特性--多态(1)
定义 对象具有多种形态 类型 引用的多态: 父类的引用指向自身对象 父类的引用指向子类对象 TrafficTool traffictool=new TrafficTool();//父类的引用指向本身类 ...
- mxnet安装及NDArray初体验
一.mxnet安装 (以下均为mac环境) 有二种方式: 1.1 用conda安装 #创建gluon目录 mkdir gluon-tutorials && cd gluon-tutor ...
- 探讨后端选型中不同语言及对应的Web框架
在进行后端选型的时候,实际上我们要选择的是一个框架.后端领域所使用的技术和框架已经趋于稳定,我们只需要按我们的需要选择所需要的框架.当存在多个框架适合时,我们再选择适合的语言.不得不指出的是,当我们喜 ...
- 各种组件的js 获取值 / js动态赋值
jQuery获取Select选择的Text和Value:语法解释:1. $("#select_id").change(function(){//code...}); //为Se ...
- Nodejs后台管理员登录实例
思路: 直接访问后台页面时如果无session则跳转到404 当在登录页的表单提交时对数据库进行匹配,匹配成功生成session,否则提示用户名或密码错误 准备页面 :后台首页.登录页.404页, 步 ...
- Sql Server中sql语句自己主动换行
怎么让sql server中的sql语句自己主动换行呢? 例如以下图: 工具--选项--全部语言 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamlhbm ...
- Knockout.Js官网学习(Mapping插件)
前言 Knockout设计成允许你使用任何JavaScript对象作为view model.必须view model的一些属性是observable的,你可以使用KO绑定他们到你的UI元素上,当这些o ...
- Java全栈程序员之04:Ubuntu下安装MySQL、注册服务及Navcat
在安装MySQL之前,我们先来介绍一下Ubuntu下软件的安装方式.首先回顾下,我们安装JDK,使用的是后缀名为tar.gz的安装包.安装idea,使用的是tar.gz:那有没有别的安装方式呢? 1. ...
- 深入理解Git (一) - 元数据
三分钟教你学Git仅仅是教我们会用Git了,但是内部的一些实现原理假设我们也知道一些的话会使我们使用起来更加顺手.这个系列就是在你用了Git一段时间之后,并想继续到Git的内部看一下到底而准备的. G ...