关于事件
  事件(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. .Net Core邮件发送之MailKit

    一 .在.Net Core中MailKit中提供了邮件的基础封装 它支持跨平台,并且支持 IMAP, POP3, SMTP 等协议 Nuget命令: Install-Package MailKit 官 ...

  2. C++11 多线程编程 使用lambda创建std::thread (生产/消费者模式)

    要写个tcp server / client的博客,想着先写个c++11多线程程序.方便后面写博客使用. 目前c++11中写多线程已经很方便了,不用再像之前的pthread_create,c++11中 ...

  3. solr之定时增量索引实现

    solr本身就提供了一个工具库实现定时增量索引,但是我在使用的过程中发现会出现一些问题,目前遇到两点: 1.启动时总是报如下异常: ? 1 The web application [solr] reg ...

  4. Android Gesture Detector

    Android Touch Screen 与传统Click Touch Screen不同,会有一些手势(Gesture),例如Fling,Scroll等等.这些Gesture会使用户体验大大提升.An ...

  5. MySQL空间索引简单使用

    简述 MySQL在5.7之后的版本支持了空间索引,而且支持OpenGIS几何数据模型.国内的MySQL相关的书籍都比较老了,在这方面有详细描述的还没有见过.有一本比较新的PostgreSQL的数据介绍 ...

  6. vim 支持 nginx配置文件 语法高亮

    1.下载 nginx.vim 语法高亮文件 2.将文件复制到 /usr/share/vim/vim74/syntax 目录(也可以是 单用户目录 ~/.vim/syntax/) 3.修改 vim /u ...

  7. 洛谷 P1016 旅行家的预算

    P1016 旅行家的预算 题目OJ链接https://www.luogu.org/problemnew/show/P1016 题目描述一个旅行家想驾驶汽车以最少的费用从一个城市到另一个城市(假设出发时 ...

  8. ios实例开发精品源码文章推荐(8.28)

    iOS源码:游戏引擎-推箱子游戏 <ignore_js_op> http://www.apkbus.com/android-106392-1-11.html iOS源码:进度条-Color ...

  9. 简单shell指令

    第一部分 简单的常用指令 1.date命令 date 2.显示日历 cal 3.显示当前目录 pwd  4.切换当前工作目录 默认情况下,超级用户的主目录是/root,而普通用户的主目录是/home下 ...

  10. R语言编程艺术#03#列表(list)

    向量的元素要求都是同类型的,而列表(list)与向量不同,可以组合多个不同类型的对象.类似于C语言中的结构体(struct)类型. 1.创建列表 从技术上讲,列表就是向理.之前我们接触过的普通向量都称 ...