关于事件
  事件(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的使用的更多相关文章

  1. CreateEvent、SetEvent、ResetEvent和WaitForSingleObject

    事件对象就像一个开关:它仅仅有两种状态---开和关.当一个事件处于"开"状态.我们称其为"有信号".否则称为"无信号". 能够在一个线程的运 ...

  2. Delphi中线程类TThread实现多线程编程2---事件、临界区、Synchronize、WaitFor……

    接着上文介绍TThread. 现在开始说明 Synchronize和WaitFor 但是在介绍这两个函数之前,需要先介绍另外两个线程同步技术:事件和临界区 事件(Event) 事件(Event)与De ...

  3. 转发 Delphi中线程类TThread 实现多线程编程

    Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大多数Delphi书藉都有说到,但基本上都是对TThread类的几个成员作一简单介绍,再说明一下Execute的实现和Synchr ...

  4. MFC中线程相关知识

    MFC中把线程分为两种类型,UI线程和工作者线程. MFC中启动一个线程的最好方法是调用AfxBeginThread,有两个版本,一个用于启动Ui线程,另外一个用于启动工作者线程.在MFC程序中,只有 ...

  5. Delphi中的线程类 - TThread详解

    Delphi中的线程类 - TThread详解 2011年06月27日 星期一 20:28 Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大多数Delphi书藉都有说到,但基本 ...

  6. Delphi中的线程类(转)

    Delphi中的线程类 (转) Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大多数Delphi书藉都有说到,但基本上都是对 TThread类的几个成员作一简单介绍,再说明一下 ...

  7. c++中CreateEvent函数

    参考:https://blog.csdn.net/u011642774/article/details/52789969 函数原型: HANDLE CreateEvent( LPSECURITY_AT ...

  8. SETEVENT的使用

    来源:https://msdn.microsoft.com/en-us/library/windows/desktop/ms686915(v=vs.85).aspx 昨天看到这个SetEvent的方法 ...

  9. windows核心编程 - 线程同步机制

    线程同步机制 常用的线程同步机制有很多种,主要分为用户模式和内核对象两类:其中 用户模式包括:原子操作.关键代码段 内核对象包括:时间内核对象(Event).等待定时器内核对象(WaitableTim ...

随机推荐

  1. JDBC(1)—Connection

    一.简介: 1.JDBC(Java Database Connectivity)是一个独立于特定数据库管理系统.通用的SQL数据库存取和操作的 *公共接口(一组API) *定义了用来访问数据库的标准j ...

  2. GoDaddy账户间域名转移PUSH以及ACCEPT接受域名过户方法

    GoDaddy账户之间的域名进行过户PUSH.以及接受ACCEPT一般发生在我们有要求代购.交易域名账户之间的处理.一般的海外域名注册商账户之间是直接可以用户交易过户的,不需要经过商家允许,但是不同的 ...

  3. AngularJS中转换响应内容

    从远程API获取到的响应内容,通常是json格式的,有时候需要对获取到的内容进行转换,比如去除某些不需要的字段,给字段取别名,等等. 本篇就来体验在AngualrJS中如何实现. 在主页面,还是从co ...

  4. android_双击退出

    /** * 设置高速双击退出程序 */ @Override public boolean onKeyDown(int keyCode, KeyEvent event) { // TODO Auto-g ...

  5. Java中的语法糖

    一.范型 1. C#和Java范型的区别 在C#中范型是切实存在的,List<int>和List<String>就是两种不同的类型,它们在系统运行期间生成,有自己的虚方法表和类 ...

  6. ReactNative: 搭建ReactNative开发环境

    搭建ReactNative开发环境 不废话,具体步骤如下: 一.安装需要的软件 1.Homebrew Homebrew, Mac系统的包管理器,用于安装NodeJS和一些其他必需的工具软件. /usr ...

  7. 卡尔曼滤波(Kalman Filter) ZZ

    一.引言 以下我们引用文献[1]中的一段话作为本文的開始: 想象你在黄昏时分看着一仅仅小鸟飞行穿过浓密的丛林.你仅仅能隐隐约约.断断续续地瞥见小鸟运动的闪现.你试图努力地猜測小鸟在哪里以及下一时刻它会 ...

  8. 2017 33 款iOS开源库

    IGListKit https://github.com/Instagram/IGListKit 由 Instagram 开发人员制作,IGListKit 是用于构建快速灵活列表的数据驱动型的 UIC ...

  9. 【Windows】Windows中解析DOS的for命令使用

    目录结构: contents structure [+] 简介 for /d ... in ... 案例 案例:打印C://根目录下所有的文件夹名称 案例:打印当前路径下,只有1-3个字母的文件夹名 ...

  10. CentOS 7 安装SVN并整合HTTP访问

    #!/bin/bash## -------------------------------------------------## 安装svn并整合http访问## ----------------- ...