CreateEvent函数在多线程中使用及实例

2023-11-09

HANDLE CreateEvent(
LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset, 
BOOL bInitialState,
LPCSTR lpName
);
bManualReset:TRUE,使用ResetEvent()手动重置为无信号状态;FALSE,当一个等待线程被释放时,自动重置状态为无信号状态。

bInitialState:指定事件对象的初始状态,当TRUE,初始状态为有信号状态;当FALSE,初始状态为无信号状态。

下面主要演示一下采用CreateEvent实现多线程。

例子很简单,主要测试CreateEvent中bManualReset:和bInitialState参数的取值在线程调用中信号状态的情况。

 

测试1:

bManualReset:TRUE
bInitialState:TRUE

CreateEvent(NULL, TRUE, TRUE, NULL); //使用手动重置为无信号状态,初始化时有信号状态

example.cpp

#include "iostream"

#include "windows.h"

using namespace std;


DWORD WINAPI ThreadProc1(LPVOID lpParam);

DWORD WINAPI ThreadProc2(LPVOID lpParam);

HANDLE hEvent = NULL;

HANDLE hThread1 = NULL;

HANDLE hThread2 = NULL;

int main(int argc, char *args[])

{

hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); //使用手动重置为无信号状态,初始化时有信号状态

//hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态

//if (SetEvent(hEvent))

//{

// cout << "setEvent 成功" <<endl;

//}

hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc1, NULL, 0,NULL);

Sleep(200);

hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc2, NULL, 0,NULL);

Sleep(200);

if ( NULL == hThread1)

{

cout <<"create thread fail!";

}

//DWORD dCount = ResumeThread(hThread);

//cout << LOWORD(dCount) << endl;

return 0;

}

DWORD WINAPI ThreadProc1(LPVOID lpParam)

{

cout <<"in thread1@!"<<endl;


DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);


if ( WAIT_OBJECT_0 == dReturn)

{

cout <<" thread1 signaled ! "<<endl;

}

cout <<"in thread1 --signal"<<endl;


//SetEvent(hEvent);

return 0;

}

DWORD WINAPI ThreadProc2(LPVOID lpParam)

{

cout <<"in thread2@!"<<endl;


DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);


if ( WAIT_OBJECT_0 == dReturn)

{

cout <<"thread2 signaled ! "<<endl;

}

cout <<"in thread2--signal"<<endl;


return 0;

}

执行结果:

从结果中看,执行完线程1又执行了线程2.

由于hEvent = CreateEvent(NULL, TRUE, TRUE, NULL),使用手动重置为无信号状态,初始化时有信号状态

所以hEvent一直处于有信号状态,无论是线程1释放后,hEvent仍处于有信号状态,所以线程2正常执行了。

 

测试2:

bManualReset:FALSE
bInitialState:TRUE

//当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态
hEvent = CreateEvent(NULL, FALSE, TRUE, NULL);

example2.cpp



#include "iostream"

#include "windows.h"

using namespace std;


DWORD WINAPI ThreadProc1(LPVOID lpParam);

DWORD WINAPI ThreadProc2(LPVOID lpParam);

HANDLE hEvent = NULL;

HANDLE hThread1 = NULL;

HANDLE hThread2 = NULL;

int main(int argc, char *args[])

{

//hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); //使用手动重置为无信号状态,初始化时有信号状态

hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态

//if (SetEvent(hEvent))

//{

// cout << "setEvent 成功" <<endl;

//}

hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc1, NULL, 0,NULL);

Sleep(200);

hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc2, NULL, 0,NULL);

Sleep(200);

if ( NULL == hThread1)

{

cout <<"create thread fail!";

}

//DWORD dCount = ResumeThread(hThread);

//cout << LOWORD(dCount) << endl;

return 0;

}

DWORD WINAPI ThreadProc1(LPVOID lpParam)

{

cout <<"in thread1@!"<<endl;


DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);


if ( WAIT_OBJECT_0 == dReturn)

{

cout <<" thread1 signaled ! "<<endl;

}

cout <<"in thread1 --signal"<<endl;


//SetEvent(hEvent);

return 0;

}

DWORD WINAPI ThreadProc2(LPVOID lpParam)

{

cout <<"in thread2@!"<<endl;


DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);


if ( WAIT_OBJECT_0 == dReturn)

{

cout <<"thread2 signaled ! "<<endl;

}

cout <<"in thread2--signal"<<endl;


return 0;

}

执行结果:


从执行结果中分析,执行了线程1,线程2一直在等待,直到主线程结束。

由于hEvent = CreateEvent(NULL, FALSE, TRUE, NULL),当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态

初始执行线程1的时候,hEvent是有信号的,所以线程1正常执行;又由于bManualReset=FALSE,所以执行完线程1后,hEvent自动重置为无信号状态,所以在线程2中,

WaitForSingleObject(hEvent,INFINITE);

函数一直在等待hEvent变为有信号状态,但是当主线程执行完,还没等待到,线程2程序一直没有走下去。

 

 

测试3:

bManualReset:TRUE
bInitialState:FALSE

hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//使用手动重置为无信号状态,初始化时为无信号状态

example3.cpp

#include "iostream"

#include "windows.h"

using namespace std;


DWORD WINAPI ThreadProc1(LPVOID lpParam);

DWORD WINAPI ThreadProc2(LPVOID lpParam);

HANDLE hEvent = NULL;

HANDLE hThread1 = NULL;

HANDLE hThread2 = NULL;

int main(int argc, char *args[])

{

//hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); //使用手动重置为无信号状态,初始化时有信号状态

//hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态

hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//使用手动重置为无信号状态,初始化时为无信号状态

//if (SetEvent(hEvent))

//{

// cout << "setEvent 成功" <<endl;

//}

hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc1, NULL, 0,NULL);

Sleep(200);

hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc2, NULL, 0,NULL);

Sleep(200);

if ( NULL == hThread1)

{

cout <<"create thread fail!";

}

//DWORD dCount = ResumeThread(hThread);

//cout << LOWORD(dCount) << endl;

return 0;

}

DWORD WINAPI ThreadProc1(LPVOID lpParam)

{

cout <<"in thread1@!"<<endl;


DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);


if ( WAIT_OBJECT_0 == dReturn)

{

cout <<" thread1 signaled ! "<<endl;

}

cout <<"in thread1 --signal"<<endl;


//SetEvent(hEvent);

return 0;

}

DWORD WINAPI ThreadProc2(LPVOID lpParam)

{

cout <<"in thread2@!"<<endl;


DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);


if ( WAIT_OBJECT_0 == dReturn)

{

cout <<"thread2 signaled ! "<<endl;

}

cout <<"in thread2--signal"<<endl;


return 0;

}

执行结果,可想而知,只能输出:

因为初始为无信号状态,所以hEvent一直处于无信号状态,因此这两个线程一直在等待,直到主线程结束。

修改:放开例子中的注释部分:

if (SetEvent(hEvent))//设置信号为有信号状态
{
cout << "setEvent 成功" <<endl;
}

执行结果:

可见,线程1和线程2都执行了。

因为调用SetEvent,事件变为有信号状态,线程1执行;又由于线程1释放后,hEvent仍旧处于有信号状态,所以线程2也执行了。

 

再修改:在线程1中,添加ResetEvent(hEvent)(手动设置事件为无信号状态),则线程2不会执行。

测试4:

bManualReset:FALSE
bInitialState:FALSE

hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);//线程释放后自动重置为无信号状态,初始化时为无信号状态

example4.cpp

#include "iostream"

#include "windows.h"

using namespace std;


DWORD WINAPI ThreadProc1(LPVOID lpParam);

DWORD WINAPI ThreadProc2(LPVOID lpParam);

HANDLE hEvent = NULL;

HANDLE hThread1 = NULL;

HANDLE hThread2 = NULL;

int main(int argc, char *args[])

{

//hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); //使用手动重置为无信号状态,初始化时有信号状态

//hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态

//hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//使用手动重置为无信号状态,初始化时为无信号状态

hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);//使用手动重置为无信号状态,初始化时为无信号状态

if (SetEvent(hEvent))

{

cout << "setEvent 成功" <<endl;

}

hThread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc1, NULL, 0,NULL);

Sleep(200);

hThread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc2, NULL, 0,NULL);

Sleep(200);

if ( NULL == hThread1)

{

cout <<"create thread fail!";

}

//DWORD dCount = ResumeThread(hThread);

//cout << LOWORD(dCount) << endl;

return 0;

}

DWORD WINAPI ThreadProc1(LPVOID lpParam)

{

cout <<"in thread1@!"<<endl;


DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);


if ( WAIT_OBJECT_0 == dReturn)

{

cout <<" thread1 signaled ! "<<endl;

}

cout <<"in thread1 --signal"<<endl;


//SetEvent(hEvent);

return 0;

}

DWORD WINAPI ThreadProc2(LPVOID lpParam)

{

cout <<"in thread2@!"<<endl;


DWORD dReturn = WaitForSingleObject(hEvent,INFINITE);


if ( WAIT_OBJECT_0 == dReturn)

{

cout <<"thread2 signaled ! "<<endl;

}

cout <<"in thread2--signal"<<endl;


return 0;

}


执行结果:

 

由于调用SetEvent,hEvent为有信号状态,线程1正常执行,又由于调用完线程1后,hEvent自动重置为无信号状态,所以线程2只能在等待,直到主线程退出。

修改:线程1中的SetEvent(hEvent);的注释去掉,再运行,则线程1和线程2 都会执行。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CreateEvent函数在多线程中使用及实例 的相关文章

  • android studio常用快捷键设置

    android开发工具androidstudio的熟练使用是提高我们开发效率的必备条件 现对android studio使用过程中的一些小技巧进行总结 1 命名规范 android开发过程中使用java语言 对变量的命名遵循驼峰命名法 一般
  • Tracy JS 小笔记 - 数据类型, typeof,类型转换

    数据类型 原始值 引用值 原始值 不可改变的原始值 是存储在栈里面 stack 是个有底儿的箱子结构先进后出 原始值 分为五大类 Number Boolean String undefined null var a 1 我们数据的类型天生就
  • Apache Pig的一些基础概念及用法总结4(转)

    26 错误 ERROR org apache pig tools grunt Grunt ERROR 2042 Error in new logical plan Try Dpig usenewlogicalplan false 的可能原因
  • decltype和declval的用法

    1 decltype是c 11以后出现的一个新的关键字 是用来萃取表达式或者变量或者函数返回值的类型的 具体用法可以参考官网 https en cppreference com w cpp language decltype 2 declv
  • 华为-人民币转换

    java实现 题目描述 考试题目和要点 1 中文大写金额数字前应标明 人民币 字样 中文大写金额数字应用壹 贰 叁 肆 伍 陆 柒 捌 玖 拾 佰 仟 万 亿 元 角 分 零 整等字样填写 2 中文大写金额数字到 元 为止的 在 元 之后
  • xss基础知识点

    xss 1 概念 跨站脚本攻击 英文全称Cross Site Script xss攻击 通常指黑客通过 HTML注入 篡改了网页 插入了恶意的脚本 从而在用户浏览网页时 控制用户浏览器的一种攻击 常见场景 标签内的xss Xss 属性里面的
  • 安装Flutter + Android sdk + vs code运行Flutter项目(史上最详解)

    前言 Flutter开发app是基于Dart语言开发的 就好比html网页开发基于JavaScript一样 而浏览器内核都可以编译JavaScript代码 所有开发html网页不需要下载啥SDK 直接在浏览器就能运行 首先我们安装Dart语
  • python 用for i in range(10)生成列表

    这种方法叫列表解析 1 列出1 10的平方和 结果用列表存储 要求 列出1 10所有数字的平方 1 普通方法 L for i in range 1 11 L append i 2 print L 1 4 9 16 25 36 49 64 8
  • 如何实现通用分页(来看我这一篇就够了超级详细内含源码!!!)

    目录 一 页面显示分页效果 1 1分析页面展示所要展示的属性有哪些 1 2分析页面有哪些每次发送请求有哪些公共的参数 二 具体实现前端通用分页 2 1分析思路 2 2具体实现的过程 2 2 1标签助手类 2 2 2创建标签库描述文件 tld
  • QTableView获取选中行指定列的内容(新手上路)

    1 第一次用QT写东西 在tableview对象后面的函数列表里翻来翻去 找了个看起来顺眼的selectedRows来试图获取选中行的内容 然后插入到list里面 QList
  • TQ2440移植u-boot2016.11全过程记录-【5】设置从NOR FLASH启动U-BOOT

    TQ2440移植u boot2016 11 设置从NOR FLASH启动u boot gedit include configs tq2440 h 屏蔽掉宏CONFIG SKIP LOWLEVEL INIT 修改宏CONFIG SYS TE
  • ModelArts平台部署模型

    相关步骤 构建镜像 上传镜像至swr服务 模型管理建立模型 部署模型上线 调用接口 1 构建自定义镜像 基于Dockfile文件构建 文件准备及文件结构 关于深度学习中的概念 训练 train 以图像识别为例 基于一个标注好的数据集训练好了
  • React-基础语法

    React 基础语法 React 搭建脚手架 安装node JS 安装React脚手架 创建项目 运行项目 其他命令 使用VSCode 安装插件 基础插件 文档目录结构 根组件App js 解析 组件解析 类组件 有状态组件 函数组件 JS
  • 软件测试项目案例哪里找?【银行/教育/商城/金融/等等....】

    项目一 ShopNC商城 项目概况 ShopNC商城是一个电子商务B2C电商平台系统 功能强大 安全便捷 适合企业及个人快速构建个性化网上商城 包含PC IOS客户端 Adroid客户端 微商城 系统PC 后台是基于ThinkPHP MVC
  • ### Paper about Event Detection

    Paper about Event Detection author gr date 2014 03 15 email forgerui gmail com 看一些相关的论文 1 Efficient Visual Event Detecti
  • 【动态规划】最少按多少下开关使灯全亮

    文章目录 无环条件下 题目描述 解题思路 递归版本 迭代版本 有环状态下 题目描述 解题思路 递归版本 迭代版本 无环条件下 题目描述 给定一个数组arr 长度为N arr中的值不是0就是1 arr i 表示第i栈灯的状态 0代表灭灯 1代
  • 介绍:教育研究:定量,定性和混合方法——伯克约翰逊,拉里克里斯滕森著

    www sagepub com bjohnson4e 章节资源的网站
  • 【图形学】GAMES101 Assignment3 作业框架分析

    GAMES101 Assignment3 作业框架分析 文章目录 GAMES101 Assignment3 作业框架分析 rasterizer draw rasterizer rasterize triangle 参考 写作业之前看了一眼代
  • java 多线程学习笔记之 线程互斥

    许多线程共享同一数据 这种情况在现实的生活中也是经常发生的 比如火车站的火车票售票系统 火车票售票系统是一个常年运行的系统 为了满足乘客的需求 我们不能只设一个窗口 必须设很多的售票窗口 每个售票窗口就像一个线程 它们各自运行 共同访问相同

随机推荐

  • GateWay 服务网关

    介绍 Cloud全家桶中有个很重要的组件就是网关 在1 x版本中都是采用的Zuul网关 但在2 x版本中 zuul的升级一直跳票 SpringCloud最后自己研发了一个网关替代Zuul 那就是SpringCloud Gateway Gat
  • 2023年kali linux安装中文输入法

    apt get install fcitx 安装输入法框架 apt get install fcitx googlepinyin 安装谷歌输入法 reboot 重启系统 重启之后右上有个小键盘点击里面的配置 添加google输入法 把Goo
  • vue2.6 Ag-grid 使用

    中文文档 ag grid中文教程 itxst com 一 HTML 结构
  • E3-1230和E3-1230 V2有多神?

    最近追E3 1230 枪E3 1230的人那叫一个多啊 都被捧成神了 我也来说说对E3 1230的看法 同档次的装机方案 我更倾向i5 2320 2500K 3570K 首 先比较两个U的规格吧 E3 1230的主频是3 2G 比i7 26
  • NVIDIA APEX安装完全指南及Megatron-LM/Pytorch运行问题解决(fused_layer_norm_cuda/packaging/amp_C/libc10.so)

    1 问题列表 在Megatron LM Pytorch运行中报错如下 No module named fused layer norm cuda apex没有装或者装的不对 注意直接用pip install apex装的不是真正的nvdia
  • 常用JS验证

    常用JS验证 共通JS Ver Date Author Comment 1 00 2016 04 25 马 新規作成 function replaceAll strvalue strRepBy strRepWith while strval
  • 从 Java 到 Go:实现一个投票和民意调查系统

    在本篇博客中 我们将探讨如何使用 Go 语言实现一个投票和民意调查系统 并从 Java 开发者的角度分析 Go 语言的特点和优势 在阅读本文之前 我们假设您已经具备一定的 Java 编程基础 文章将通过具体的代码示例 帮助您更轻松地从 Ja
  • windows下的命令行工具babun

    什么是babun babun是windows上的一个第三方shell 在这个shell上面你可以使用几乎所有linux unix上面的命令 他几乎可以取代windows的shell 用官方的题目说就是A Windows shell you
  • Linux中部署Spring Cloud项目

    Linux中部署Spring Cloud项目 文章为本人在学习的过程中 记录部署过程 仅供参考学习 因本人经验不足 教程或有不妥之处 还望指正 保姆级教程 敬请食用 简介 在学习过程中 部署时使用的项目是一个个人学习项目 若您喜欢 也可点击
  • Linux-压缩命令

    目录 1 tar 1 1 压缩 tar gz tar bz2 tgz 1 2 解压缩 tar gz tar bz2 tgz 2 zip 2 1 压缩 zip 2 2 解压缩 zip 3 rar 3 1 压缩 rar 3 2 解压缩 rar
  • 强大性能分析工具JVisualVM

    JVisualVM是由Sun提供的性能分析工具 如此强大的后盾怎能不强大 在Jdk6 0以后的版本中是自带的 配置好环境变量然后在运行中输入 JVisualVm 或直接到Jdk的安装目录的Bin目录下找到运行程序即可运行 如果是用Jdk1
  • 静态测试 动态测试 白盒测试的优缺点

    静态分析是一种不通过执行程序而进行测试的技术 静态分析的关键功能是检查软件的表示和描述是否一致 没有冲突或者没有歧义 动态分析的主要特点是当软件系统在模拟的或真实的环境中执行之前 之中和之后 对软件系统行为的分析 动态分析包含了程序在受控的
  • C语言 字母大小互相转换 三种思路

    1 利用ASCII值方法 大小写相差32 方法 1 include
  • maven在Win10的安装和配置

    1 下载和安装maven 一 下载Maven并解压 1 Maven官网下载地址 http maven apache org download cgi 2 下载后解压 将Maven的压缩包解压到 E Java apache maven 3 6
  • 【Unity2D入门教程】简单制作一个弹珠游戏之制作场景①(开场,结束,板子,球)

    学习目标 看过我前面的文章应该知道怎么制作开头和结尾 这里我简单把效果给大伙看一下 我用的游戏分辨率是4 3 因此我们要改变Canvas的的Cavans Scale为X1440 Y1080 结束的场景也一样 接着我们编写一个脚本来管理场景的
  • 基于人工势场算法机器人避障路径规划

    基于人工势场算法机器人避障路径规划 人工势场算法是一种热门的机器人路径规划算法 其通过建立虚拟的 势场 使得机器人在避障时能够像物理学中的粒子一样受到 势 的作用 最终实现自主导航 本文将介绍如何使用 MATLAB 实现基于人工势场算法的机
  • mac中的IDEA的使用快捷键

    1 command F 在当前文件进行文本查找 2 command shift F 进行工程和模块中的文件搜索 3 command u 找到这个方法的接口 4 command option commad 找到这个接口的实现类 5 comma
  • javascript中做减法时,出现小数位增加bug

    这个bug是js固有的 浮点数精度不准 你可以用下面方法来解决 思路是先放大 求和 差 积等运算后再缩小 如 加法函数 用来得到精确的加法结果 说明 javascript的加法结果会有误差 在两个浮点数相加的时候会比较明显 这个函数返回较为
  • JPEG编码原理及文件格式及代码分析

    一 JPEG编码原理 首先我们先来看一下JPEG的编码原理图 如上图所示 下面进行逐步的分析 1 RGB gt YUV 首先为了降低互相的关联性 将RGB转换为YUV 这样就可以对亮度信号和色度信号进行分别的处理 2 零电平偏置下移 由于后
  • CreateEvent函数在多线程中使用及实例

    HANDLE CreateEvent LPSECURITY ATTRIBUTES lpEventAttributes BOOL bManualReset BOOL bInitialState LPCSTR lpName bManualRes