4937|11

65

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

100分 关于一个程序流程的问题 [复制链接]

请教各位帮忙单步跟踪一下下面这个程序
#include   "stdafx.h"   
  #include      
  #include      
  using   namespace   std;   
   
  #define   THREAD_NUM   5   
  HANDLE   g_Event;   
  HANDLE   event[THREAD_NUM];   
  DWORD   WINAPI   ThreadFunc(LPVOID);   
   
  int   main(int   argc,   char*   argv[])   
  {   
  HANDLE   hThrd[THREAD_NUM];   
  g_Event=::CreateEvent(NULL,TRUE,FALSE,NULL);   
  for   (int   i=0;i   {   
  event=::CreateEvent(NULL,TRUE,FALSE,NULL);   
  }   
  for   (i=0;i   {   
  hThrd=::CreateThread(NULL,0,ThreadFunc,(LPVOID)i,0,NULL);   
  if   (hThrd!=NULL)   
  {   
  cout<<"Thread"<   }   
  }   
  WaitForMultipleObjects(THREAD_NUM,event,TRUE,INFINITE);   
  PulseEvent(g_Event);   
  WaitForMultipleObjects(THREAD_NUM,hThrd,TRUE,INFINITE);   
  for   (i=0;i   {   
  CloseHandle(event);   
  CloseHandle(hThrd);   
  }   
  CloseHandle(g_Event);   
  cout<<"Process   Finished"<   return   0;   
  }   
   
  DWORD   WINAPI   ThreadFunc(LPVOID   n)   
  {   
  SetEvent(event[(int)n]);   
  while   (TRUE)   
  {   
  switch(WaitForSingleObject(g_Event,INFINITE))   
  {   
  case   WAIT_OBJECT_0:   
  printf("Thread%d   WAIT_OBJECT_0\n",(int)n+1);   
  return   0;   
  break;   
  default:   
  break;   
  }   
  }   
  return   0;   
  }   
我不理解它的执行顺序
看的很迷糊
请各位高手帮忙指点一下
象调试程序一样,帮忙讲讲程序每步向下运行执行到哪?为什么?
谢谢各位

最新回复

人工重置事件的PulseEvent和自动重置事件的SetEvent函数之间的不同之处在于用SetEvent处理自动重置事件将只释放一个线程来运行,即使有许多线程在等待那个事件。而PulseEvent将释放所有等待那个事件的线程。以上摘自《WINCE程序设计》里。   详情 回复 发表于 2008-8-29 23:00
点赞 关注

回复
举报

76

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
你程序就这么几句? 开了一个线程而已 也没有执行什么啊
 
 

回复

67

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
  红字的地方把我搞晕了:
  #include  "stdafx.h"  
  #include    
  #include    
  using  namespace  std;  
   
  #define  THREAD_NUM  5  
  HANDLE  g_Event;  
  HANDLE  event[THREAD_NUM];  
  DWORD  WINAPI  ThreadFunc(LPVOID);  
   
  int  main(int  argc,  char*  argv[])  
  {  
  HANDLE  hThrd[THREAD_NUM];  
  g_Event=::CreateEvent(NULL,TRUE,FALSE,NULL);  
  for  (int  i=0;i   {  
  event=::CreateEvent(NULL,TRUE,FALSE,NULL);  
  }  
  for  (i=0;i   {  
  hThrd=::CreateThread(NULL,0,ThreadFunc,(LPVOID)i,0,NULL);  
  if  (hThrd!=NULL)  
  {  
  cout < <"Thread" <   }  
  }  
  WaitForMultipleObjects(THREAD_NUM,event,TRUE,INFINITE);  
  PulseEvent(g_Event);  
  WaitForMultipleObjects(THREAD_NUM,hThrd,TRUE,INFINITE);  

  for  (i=0;i   {  
  CloseHandle(event);  
  CloseHandle(hThrd);  
  }  
  CloseHandle(g_Event);  
  cout < <"Process  Finished" <   return  0;  
  }  
   
  DWORD  WINAPI  ThreadFunc(LPVOID  n)  
  {  
  SetEvent(event[(int)n]);
  while  (TRUE)  
  {  
switch(WaitForSingleObject(g_Event,INFINITE))  
  {  
  case  WAIT_OBJECT_0:  
  printf("Thread%d  WAIT_OBJECT_0\n",(int)n+1);  
  return  0;  
  break;  
  default:  
  break;  
  }  
  }  
  return  0;  
  }  
这些waitForSingleObject和WaitForMultipleObjects什么时候被触发使能?
 
 
 

回复

60

帖子

0

TA的资源

一粒金砂(初级)

4
 
首先主线程创建n的线程,然后等待n个线程触发event

子线程触发event等待主线程触发g_Event

主线程在n个线程都触发了event后,触发g_Event,使得所有子线程可以继续执行
然后主线程等待所有子线程都退出后,继续执行,即WaitForMultipleObjects(THREAD_NUM,hThrd,TRUE,INFINITE)后的代码
 
 
 

回复

84

帖子

0

TA的资源

一粒金砂(初级)

5
 
建立一堆事件,建立一堆线程。
一个线程对应一个事件。

1、
WaitForMultipleObjects(THREAD_NUM,event,TRUE,INFINITE);  
第三个参数是true。

意思是需要等到event数组中的事件全部被setevent后才能被激活。
就是要所有线程都跑到switch(WaitForSingleObject(g_Event,INFINITE))  这一步。

2、
PulseEvent(g_Event);  
//激活事件。
然所有线程都可以从
switch(WaitForSingleObject(g_Event,INFINITE))
往下执行,并退出。

3、
WaitForMultipleObjects(THREAD_NUM,hThrd,TRUE,INFINITE);  

意思是需要等到hThrd数组中的事件全部被setevent后才能被激活。
但是hThrd中保存的是线程句柄,那么就是所有hThrd中的线程都退出后,
才能被激活,开始执行下面的代码


 
 
 

回复

79

帖子

0

TA的资源

一粒金砂(初级)

6
 
  #include  "stdafx.h"  
  #include    
  #include    
  using  namespace  std;  
   
  #define  THREAD_NUM  5  
  HANDLE  g_Event;  
  HANDLE  event[THREAD_NUM];  
  DWORD  WINAPI  ThreadFunc(LPVOID);  
   
  int  main(int  argc,  char*  argv[])  
  {  
  HANDLE  hThrd[THREAD_NUM];  
  g_Event=::CreateEvent(NULL,TRUE,FALSE,NULL);   0
  for  (int  i=0;i   {  
  event=::CreateEvent(NULL,TRUE,FALSE,NULL);    1
  }  
  for  (i=0;i   {  
  hThrd=::CreateThread(NULL,0,ThreadFunc,(LPVOID)i,0,NULL);   2
  if  (hThrd!=NULL)  
  {  
  cout < <"Thread" < 3
  }  
  }  
  WaitForMultipleObjects(THREAD_NUM,event,TRUE,INFINITE);  4
  PulseEvent(g_Event);                                     6  
  WaitForMultipleObjects(THREAD_NUM,hThrd,TRUE,INFINITE);  8
  for  (i=0;i   {  
  CloseHandle(event);  
  CloseHandle(hThrd);  
  }  
  CloseHandle(g_Event);  
  cout < <"Process  Finished" <   return  0;  
  }  
   
  DWORD  WINAPI  ThreadFunc(LPVOID  n)  
  {  
  SetEvent(event[(int)n]);       5
  while  (TRUE)  
  {  
  switch(WaitForSingleObject(g_Event,INFINITE))     7
  {  
  case  WAIT_OBJECT_0:  
  printf("Thread%d  WAIT_OBJECT_0\n",(int)n+1);      9
  return  0;  
  break;  
  default:  
  break;  
  }  
  }  
  return  0;  
  }  
程序流程:
  <1>进入main函数中,
  <2>首先创建了1个事件g_Event和i个事件event和i个线程hThrd  如程序上 0,1,2
  <3>这时,在主线程中打印:"Threadi Lauched" ,
     并在第一个WaitForMultipleObjects(THREAD_NUM,event,TRUE,INFINITE);中等待event信号触发,  
     同时线程ThreadFunc(i个线程同时运行)启动,进入第一个SetEvent(event[(int)n]);
     触发了所有event事件   如程序上的3,4,5
  <4>因为这时子线程已经触发了事件组event
     所以主线程WaitForMultipleObjects(THREAD_NUM,event,TRUE,INFINITE);通过
      执行PulseEvent(g_Event);这条语句,
      同时所有i个子线程都卡到switch(WaitForSingleObject(g_Event,INFINITE))等待g_Event事件被触发,
      如程序上的6,7
   <5>这时主线程又卡在第二个WaitForMultipleObjects(THREAD_NUM,hThrd,TRUE,INFINITE); 等待hThrd被触发?????/
      而i个子线程都因为主线程执行了PulseEvent(g_Event);这条语句后触发了switch(WaitForSingleObject(g_Event,INFINITE))
      语句,打印出:printf("Thread%d  WAIT_OBJECT_0\n",(int)n+1); 这条
       如程序上的8,9
    <6>最后程序是如何触发这条WaitForMultipleObjects(THREAD_NUM,hThrd,TRUE,INFINITE);
      使程序最终打印出:cout < <"Process  Finished" <
问题:
   1、我理解的这个程序流程是不是有问题的?
   2、如<5>、<6>中所问:等待hThrd被触发?是怎么一回事,
      最后程序是如何触发这条WaitForMultipleObjects(THREAD_NUM,hThrd,TRUE,INFINITE);???
   3、PulseEvent(g_Event);这条是激活所有事件,可是参数g_Event只是单独定义的一个事件:g_Event=::CreateEvent(NULL,TRUE,FALSE,NULL);
      而多事件:event=::CreateEvent(NULL,TRUE,FALSE,NULL);是通过对应的多个线程ThreadFunc(LPVOID  n) 中SetEvent(event[(int)n]);
      激活的,而不是通过 PulseEvent激活的啊 ???
 
 
 

回复

79

帖子

0

TA的资源

一粒金砂(初级)

7
 
1. 我的理解和你是一样的
2. Wait一个线程就是等待这个线程结束
3. 问题看不太明白,不过PulseEvent其实和SetEvent是差不多的,只不过PulseEvent在触发Event后会把Event再设成未触发,如果PulseEvent的时候如果子线程还没有WaitSingleObject,那么它会错过这个Event
   所以这段代码在非常小的概率下,主线程会挂住
 
 
 

回复

88

帖子

0

TA的资源

一粒金砂(初级)

8
 
6,7的顺序不对。

按道理应该是7先完成,然后才是6.

PulseEvent在这里的目的是让所有的线程都能从wait中解放,并退出。

而线程的全部退出就使主线程能安全退出。


如6楼所说,可能会有问题。
就是最后一个线程
SetEvent后,cpu就切到主线程执行PulseEvent。
在这种情况下就死锁了。


WaitForMultipleObjects(THREAD_NUM,event,TRUE,INFINITE);
后可以有一个sleep的延迟
或者直接把PulseEvent改为SetEvent
 
 
 

回复

72

帖子

0

TA的资源

一粒金砂(初级)

9
 
二位果然是强人!!!
这个程序是因为在PulseEvent后没有Sleep();
造成本意激活5个线程,而现在只能激活4个线程

可是为什么要用PulseEvent而不用SetEvent呢??
是因为人工重置事件必须用PulseEvent(因为PulseEvent可以触发event后自动再设成未触发)吗??
还是因为多事件多线程需要用到这个函数PulseEvent
或者是其他原因???
感谢各位解答!
 
 
 

回复

75

帖子

0

TA的资源

一粒金砂(初级)

10
 
这个还真没仔细想过 我很少用PulseEvent
不同情况有不同用法吧
 
 
 

回复

80

帖子

0

TA的资源

一粒金砂(初级)

11
 
mark学习
 
 
 

回复

64

帖子

0

TA的资源

一粒金砂(初级)

12
 
引用 8 楼 wangxin_801115 的回复:
二位果然是强人!!!
这个程序是因为在PulseEvent后没有Sleep();
造成本意激活5个线程,而现在只能激活4个线程

可是为什么要用PulseEvent而不用SetEvent呢??
是因为人工重置事件必须用PulseEvent(因为PulseEvent可以触发event后自动再设成未触发)吗??
还是因为多事件多线程需要用到这个函数PulseEvent
或者是其他原因???
感谢各位解答!


人工重置事件的PulseEvent和自动重置事件的SetEvent函数之间的不同之处在于用SetEvent处理自动重置事件将只释放一个线程来运行,即使有许多线程在等待那个事件。而PulseEvent将释放所有等待那个事件的线程。以上摘自《WINCE程序设计》里。
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表