热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

基于visualc++之windows核心编程代码分析(14)使用Event同步线程

我们进行Windows编程编写多线程程序的时候经常需要用到线程同步,我们来实现用Event同步线程。请见代码注释与实例讲解。[cpp]viewplaincopy*头文件*#incl

我们进行Windows编程编写多线程程序的时候经常需要用到线程同步,我们来实现用Event同步线程。

请见代码注释与实例讲解。

 

[cpp] view plain copy
  1. /* 头文件 */  
  2. #include   
  3. #include   
  4. /* 常量定义 */  
  5. #define NUMTHREADS  3   
  6. #define BUFFER_SIZE 16  
  7. #define FOR_TIMES   5  
  8. /* 全局变量 */  
  9. HANDLE hWriteEvent[NUMTHREADS];     // 写Event 表示写操作是否完成  
  10. HANDLE hReadEvents[NUMTHREADS]; // 读Event 表示读操作是否完成  
  11. BYTE lpSharedBuffer[16] = {0};  // 共享内存  
  12. /* 函数声明 */  
  13. void MultiEvents(void);  
  14. VOID WriteToBuffer(VOID);  
  15. DWORD WINAPI ThreadFunction(LPVOID lpParam);  
  16.   
  17. /************************************* 
  18. * int main(void) 
  19. * 功能    演示 
  20. * 
  21. * 参数    未使用 
  22. **************************************/  
  23. int main()  
  24. {  
  25.     MultiEvents();  
  26. }  
  27.   
  28. /************************************* 
  29. * void UseEvents(void)  
  30. * 功能    演示Event的使用方法 
  31. * 
  32. * 参数    未使用 
  33. **************************************/  
  34. void MultiEvents(void)   
  35. {  
  36.     HANDLE hThread;   
  37.     DWORD i;   
  38.     // 创建多个线程,读共享内存,主线程写共享内存。  
  39.     // 每个线程都有对应的读写同步事件  
  40.     for(i = 0; i < NUMTHREADS; i++)   
  41.     {  
  42.         // 每个线程都有一个Event表示写入操作完成  
  43.         hWriteEvent[i] = CreateEvent(   
  44.             NULL,           // 默认安全属性  
  45.             FALSE,          // 自动重置  
  46.             FALSE,          // 初始为未置位的  
  47.             NULL            // 未命名  
  48.             );  
  49.         // 判断是否创建成功  
  50.         if (hWriteEvent[i] == NULL)   
  51.         {   
  52.             printf("CreateEvent failed (%d)\n", GetLastError());  
  53.             return;  
  54.         }  
  55.         // 每个读线程有一个Event表示读操作已经完成  
  56.         hReadEvents[i] = CreateEvent(   
  57.             NULL,     // 默认安全属性  
  58.             FALSE,    // 自动重置  
  59.             FALSE,    // 初始化为未置位的  
  60.             NULL);    // 未命名  
  61.         if (hReadEvents[i] == NULL)   
  62.         {  
  63.             printf("CreateEvent failed (%d)\n", GetLastError());  
  64.             return;  
  65.         }  
  66.         // 创建线程  
  67.         hThread = CreateThread(NULL, 0,   
  68.             ThreadFunction,   
  69.             (LPVOID)i,  // Event对象句柄作为  
  70.             0, NULL);   
  71.         if (hThread == NULL)   
  72.         {  
  73.             printf("CreateThread failed (%d)\n", GetLastError());  
  74.             return;  
  75.         }  
  76.     }  
  77.     WriteToBuffer();  
  78. }  
  79.   
  80. /************************************* 
  81. * VOID WriteToBuffer(INT iContent)  
  82. * 功能    由主线程调用,向共享内存中写入数据 
  83. *       等待所有读线程读完后函数返回 
  84. * 
  85. * 参数    未使用 
  86. **************************************/  
  87. VOID WriteToBuffer(VOID)   
  88. {  
  89.     DWORD dwWaitResult, j,i;  
  90.     // 完成 FOR_TIMES 次读写  
  91.     for (j = 0; j < FOR_TIMES; j++)  
  92.     {         
  93.         Sleep(rand()%100);  // 写入需要的时间随机  
  94.         // 写入共享内存  
  95.         wsprintf(lpSharedBuffer,"shared %d",j);  
  96.         // 将线程对应的写Event置为“标志的”,表示写操作完成,  
  97.         // 其他线程可以开始读  
  98.         for(i=0; i
  99.         {  
  100.             if (! SetEvent(hWriteEvent[i]) )   
  101.             {   
  102.                 printf("SetEvent failed (%d)\n", GetLastError());  
  103.                 return;  
  104.             }  
  105.         }  
  106.         // 等待所有的线程读完,开始下次写入  
  107.         dwWaitResult = WaitForMultipleObjects(   
  108.             NUMTHREADS,   // Event句柄的个数  
  109.             hReadEvents,  // Event句柄数组  
  110.             TRUE,         // 等到所有的Event都被标志  
  111.             INFINITE);    // 无限等待  
  112.         // 判断等待结果  
  113.         if (dwWaitResult != WAIT_OBJECT_0)   
  114.         {  
  115.             printf("Wait error: %d\n", GetLastError());   
  116.             ExitProcess(0);   
  117.         }  
  118.     }  
  119. }  
  120.   
  121. /************************************* 
  122. * DWORD WINAPI ThreadFunction(LPVOID lpParam) 
  123. * 功能    线程函数,读共享内存 
  124. * 
  125. * 参数    LPVOID lpParamt 实际为指向Event句柄的指针 
  126. **************************************/  
  127. DWORD WINAPI ThreadFunction(LPVOID lpParam)   
  128. {  
  129.     DWORD dwWaitResult;  
  130.     BYTE lpRead[16];  
  131.     DWORD j = 0;  
  132.     DWORD dwThreadIndex  = (DWORD)lpParam;  
  133.     // 完成 FOR_TIMES 次读写  
  134.     for(; j
  135.     {  
  136.         // 等待写事件置位,表示数据已经写入  
  137.         dwWaitResult = WaitForSingleObject(   
  138.             hWriteEvent[dwThreadIndex], // Event 句柄  
  139.             INFINITE);                  // 无限等待  
  140.         switch (dwWaitResult)   
  141.         {  
  142.         case WAIT_OBJECT_0:  
  143.             Sleep(rand()%10);           // 模拟数据处理所需的时间随机  
  144.             CopyMemory(lpRead,lpSharedBuffer,16);  
  145.             break;   
  146.             // 发生错误  
  147.         default:   
  148.             printf("Wait error: %d\n", GetLastError());   
  149.             ExitThread(0);   
  150.         }  
  151.         // 将读Event置位,表示读操作完成  
  152.         if (! SetEvent(hReadEvents[dwThreadIndex]) )   
  153.         {   
  154.             printf("SetEvent failed (%d)\n", GetLastError());  
  155.             return 0;  
  156.         }  
  157.         //打印读到的内容  
  158.         printf("线程 %u\t第 %d 次读,内容:%s\n",  
  159.             dwThreadIndex,j,(LPSTR)lpRead);  
  160.     }  
  161.     return 1;  
  162. }  


推荐阅读
  • PBO(PixelBufferObject),将像素数据存储在显存中。优点:1、快速的像素数据传递,它采用了一种叫DMA(DirectM ... [详细]
  • vue引入echarts地图的四种方式
    一、vue中引入echart1、安装echarts:npminstallecharts--save2、在main.js文件中引入echarts实例:  Vue.prototype.$echartsecharts3、在需要用到echart图形的vue文件中引入:   importechartsfrom&amp;quot;echarts&amp;quot;;4、如果用到map(地图),还 ... [详细]
  • WPF项目学习.一
    WPF项目搭建版权声明:本文为博主初学经验,未经博主允许不得转载。一、前言记录在学习与制作WPF过程中遇到的解决方案。使用MVVM的优点是数据和视图分离,双向绑定,低耦合,可重用行 ... [详细]
  • 本文详细介绍了 HTML 中 a 标签的 href 属性的多种用法,包括实现超链接、锚点以及调用 JavaScript 方法。通过具体的示例和解释,帮助开发者更好地理解和应用这些技术。 ... [详细]
  • 基于iSCSI的SQL Server 2012群集测试(一)SQL群集安装
    一、测试需求介绍与准备公司计划服务器迁移过程计划同时上线SQLServer2012,引入SQLServer2012群集提高高可用性,需要对SQLServ ... [详细]
  • VB.net 进程通信中FindWindow、FindWindowEX、SendMessage函数的理解
    目录一、代码背景二、主要工具三、函数解析1、FindWindow:2、FindWindowEx:3、SendMessage: ... [详细]
  • Python 数据可视化实战指南
    本文详细介绍如何使用 Python 进行数据可视化,涵盖从环境搭建到具体实例的全过程。 ... [详细]
  • 装饰者模式(Decorator):一种灵活的对象结构设计模式
    装饰者模式(Decorator)是一种灵活的对象结构设计模式,旨在为单个对象动态地添加功能,而无需修改原有类的结构。通过封装对象并提供额外的行为,装饰者模式比传统的继承方式更加灵活和可扩展。例如,可以在运行时为特定对象添加边框或滚动条等特性,而不会影响其他对象。这种模式特别适用于需要在不同情况下动态组合功能的场景。 ... [详细]
  • 在尝试对 QQmlPropertyMap 类进行测试驱动开发时,发现其派生类中无法正常调用槽函数或 Q_INVOKABLE 方法。这可能是由于 QQmlPropertyMap 的内部实现机制导致的,需要进一步研究以找到解决方案。 ... [详细]
  • 本文通过基准测试(Benchmark)对.NET Core环境下Thrift和HTTP客户端的微服务通信性能进行对比分析。基准测试是一种评估系统或组件性能的方法,通过运行一系列标准化的测试来衡量其表现。 ... [详细]
  • 面试题总结_2019年全网最热门的123个Java并发面试题总结
    面试题总结_2019年全网最热门的123个Java并发面试题总结 ... [详细]
  • iOS snow animation
    CTSnowAnimationView.hCTMyCtripCreatedbyalexon1614.Copyright©2016年ctrip.Allrightsreserved.# ... [详细]
  • Ext JS MVC系列一:环境搭建与框架概览
    本文主要介绍了如何在项目中使用Ext JS 4作为前端框架,并详细讲解了Ext JS 4的MVC开发模式。文章将从项目目录结构、相关CSS和JS文件的引用以及MVC框架的整体认识三个方面进行总结。 ... [详细]
  • window下的python安装插件,Go语言社区,Golang程序员人脉社 ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
author-avatar
bw32dts
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有