WaitForMultipleObjects 多个线程同时触发的问题

Rivera_Biti 2008-02-29 03:54:02

DWORD WaitForMultipleObjects(
DWORD nCount,
const HANDLE* lpHandles,
BOOL bWaitAll, //bWaitAll = false, 问题均是基于 该参数为 false的情况
DWORD dwMilliseconds
);

仔细看了MSDN,可还是有几个问题不懂。

1.句柄数组是否需要进行紧缩操作,即当某个线程被激活之后,可以得到该线程在数组中的下标号,然后对其进行一些操作,操作完毕之后是否需要将该句柄从数组中去除呢(就是前面说的紧缩的操作)?
侯先生翻译的 “Win32多线程设计” 中没有提到这一点,只是说MsgWaitForMultipleObjects 需要进行此类操作,但是为什么这个函数就需要呢??和消息循环队列有关系吗??

2.多个内核对象被触发时,WaitForMultipleObjects选择其中序号最小的返回。这儿又会产生一个问题,如果序号最小的那个对象频繁被触发,那么序号比它大的内核对象将的不到被出理的机会,可以采用双WaitForMultipleObjects检测机制来实现。
这一段我是从网上看到的,估计各位高手也都看过,他的代码中有一处我不是很明白,希望赐教

DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
DWORD dwRet = 0;
int nIndex = 0;
while(1)
{
dwRet = WaitForMultipleObjects(nCount,pHandles,false,INFINITE);

switch(dwRet)
{
case WAIT_TIMEOUT:
break;
case WAIT_FAILED:
return 1;
default:
{
nIndex = dwRet - WAIT_OBJECT_0;
ProcessHanlde(nIndex++);
//同时检测其他的事件
while(nIndex < nCount)
{
dwRet = WaitForMultipleObjects(nCount - nIndex,&pHandles[nIndex],false,0); //问题在这里,为什么数组句柄为 &pHandles[nIndex],还是pHandles可以吗?
//而且,我看到这样的处理,我觉得没有必要做句柄数组的紧缩处理
switch(dwRet)
{
case WAIT_TIMEOUT:
nIndex = nCount; //退出检测,因为没有被触发的对象了.
break;
case WAIT_FAILED:
return 1;
default:
{
nIndex = dwRet - WAIT_OBJECT_0;
ProcessHanlde(nIndex++);
}
break
}
}
}
break;
}
}
return 0;
}

手头没有编译环境,所以无法试验,只要先把代码粘上来了,呵呵
问得问题比较仓促,大家见谅,嗯。。。先放100分吧

ps:请不要说先去看看书才来提问类似的话,因为我真是看了好久还是不明白,谢谢大家
...全文
461 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
Rivera_Biti 2008-03-01
  • 打赏
  • 举报
回复
就是 那个 相当于 子集 的用法

可以这么弄??
Rivera_Biti 2008-03-01
  • 打赏
  • 举报
回复
哦。。。

可是数组有这个用法吗??

抱歉,基础太差了。。。

ps:手头还是没有环境,出差中,只能在网吧弄了
yebeans 2008-03-01
  • 打赏
  • 举报
回复
对,差不多就是这个意思。
Rivera_Biti 2008-03-01
  • 打赏
  • 举报
回复
to cnzdgs

非常感谢,但还有一点疑问

假如是非自动复位类型,而且我不做紧缩或者排除操作,那么其实就等于函数内部会多等待一个线程激活状态,虽然这个线程状态永远也不会激活,也就是说,只是增加了函数的负载,但是并不会产生问题,可以这样说吗??也就说,如果在非自动复位类型里面我没有做紧缩操作,会产生什么样的问题呢??

to yebeans
比如 现在线程句柄号 0 1 2 3 4 ,下标2和3的线程同时被激活,那么首先处理2,然后在while循环里面对其他线程进行检测,检测出来3也被触发了,那么看这个函数
此时 nCount = 5; nIndex = 3;
WaitForMultipleObjects(nCount-nIndex,&pHandles[nIndex],false,0);

就变成了 WaitForMultipleObjects(5-3,&pHandles[3],false,0);

&pHandles 相等于 pHandles[]的一个子集subpHandles[],subpHandles的长度为2,而且 pHandles[3] == subpHandles[0],pHandles[4] = subpHandles[1];
也就是说,现在函数就变成了

WaitForMultipleObjects(5-3,subpHandles,false,0);

这样理解对吗??

谢谢各位

cnzdgs 2008-03-01
  • 打赏
  • 举报
回复
LZ现在差不多都理解对了。
1、多等待几个对象的开销通常可以忽略。
2、数组的子集只要是连续的就可以。
Rivera_Biti 2008-03-01
  • 打赏
  • 举报
回复
看来我对这个函数的理解出现偏差了,呵呵,明白了,散分
yebeans 2008-03-01
  • 打赏
  • 举报
回复
那个用法是C/C++语言基础吧。。。。
WaitForMultipleObjects(nCount,pHandles,false,INFINITE);
nCount和pHandles就是相当于传递一个内存长度(只不过这里是以sizeof(HANDLE)计数)和内存地址。
内存地址后移,把长度减小,保证不越界怎么用都行。
yebeans 2008-02-29
  • 打赏
  • 举报
回复
不知道你说的数组紧缩是想表达个什么意思。

那个while循环就是为了防止低索引的句柄事件频繁而导致高索引“挨饿”的情况,比如0号事件频繁,如果如果总是Wait整个数组,那么就返回的dwRet总是等于 WAIT_OBJECT_0,而后面的事件就得不到处理。所以就要把已经处理的排除掉,去检查后面的事件。

WaitForMultipleObjects(nCount - nIndex,&pHandles[nIndex],false,0); 这句不是等待事件,而是去检查事件(注意他的超时值是0)
&pHandles[nIndex] 这个就是取数组第nIndex个元素的地址,就是事件数组的起始地址向后移到第nIndex个元素的位置,而后面就还剩下nCount-nIndex个元素。
cnzdgs 2008-02-29
  • 打赏
  • 举报
回复
第1个问题,你理解反了。等待函数是在对象被设置为有信号状态时才返回的,对于自动复位类型的对象,在执行完等待函数后自动复位变为无信号状态,所以再次等待时不会有影响。而对于手动复位类型的对象,在执行完等待函数后其状态不变,可根据情况将其手动复位或者紧缩将其排除。

第2个问题,与对象是否自动复位有关。如果对象不是自动复位,则不能改为pHandles。

另外需要注意,PulseEvent这个函数触发事件是将事件设置为有信号状态然后立即又改为无信号,有些类似于自动复位。
Rivera_Biti 2008-02-29
  • 打赏
  • 举报
回复
to cnzdgs

第一个知道了,可不可以这样理解,如果属于自动复位类型的,那么其被触发过一次之后,出于具体情况,可能不再需要对其进行处理,所以需要紧缩将其排除掉,防止下次其触发还被处理(因为它的下标号或许组小),这样理解可以吗??

第二个问题的 &pHandles[nIndex] 还是不明白,akiraya 说是可以减少等待的句柄数量,可是我觉得,除非此时把句柄数组紧缩,要不然等待的还是nCount个句柄,并不会减少等待句柄的数量
cnzdgs 2008-02-29
  • 打赏
  • 举报
回复
1、WaitForMultipleObjects不会主动去改变对象的状态,WaitForMultipleObjects返回后,触发的对象一般是保持有信号状态,但如果该对象是自动复位类型的,则会自动变为无信号状态。至于是否要进行紧缩操作则根据实际的需要来决定。
2、前面的问题如果理解了,这个问题不用回答了吧。
Rivera_Biti 2008-02-29
  • 打赏
  • 举报
回复
恩。。

不对吧

dwRet = WaitForMultipleObjects(nCount - nIndex,&pHandles[nIndex],false,0);

&pHandles[nIndex]这样写是从 nIndex开始找吗??

执行一次之后,是只有(nCount-1)个句柄需要等待,但是这样写就是只等(nCount-1)个句柄吗?我感觉还是需要等(nCount)个吧。因为没有发现对这个pHandles数组进行紧缩的操作,将其长度由 nCount 变为 (nCount-1)
Rivera_Biti 2008-02-29
  • 打赏
  • 举报
回复
哦哦,明白了,多谢 akiraya 阿

那个,我的第一个问题,那个关于紧缩的问题,可以赐教吗??多谢

  • 打赏
  • 举报
回复
还是pHandles可以吗?
===================
当然可以了,只不过这样的话等待的句柄就多了。
这个应该是根据实际的情况得到的方法。

64,701

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧