100分请教高手: 关于信号量的一个问题

时间:2022-12-11 15:16:40
   关于SetEvent(hEvent)与WaitForSingleObject配合使用的时候,发现如下情况:
   hEvent是自复位的信号量.
   我在一个线程内连续执行了100次SetEvent(hEvent);按道理,等待在另一个线程的
WaitForSingleObject也应该激活100次,但实际上经常发现少激活一次.
   我估计是连续执行了100次SetEvent(hEvent)的时候,另一个线程的WaitForSingleObject
还没有来得及处理而遗漏了.
   请问,问题是我估计的吗?  比如我是否可以在每次执行SetEvent(hEvent)前判断一下,前次hEvent的状态.

   如何解决这个问题呢? ???

9 个解决方案

#1


首先我也想知道在不使用WaitForSingleObject这类API的前提下如何检测Event的状态,
其次LZ看看在_beginthreadex的时候线程初始化状态为挂起or运行?

#2


如果是单个线程等待自复位的信号量,因该不会出现上述问题,你把代码贴出来才好分析。

#3


不使用等待函数是无法检测事件状态的

#4


SetEvent 100次并不代表WaitForSingleObject会激活100次。

#5


如果你的本意是一个事件激发一次一个线程的wait,以执行某一段代码,最后使得事件数和执行代码数一直,可以用如下方法,响应事件的处理代码:


//事件来临,则
while (TRUE)
{
if (WAIT_TIMEOUT == WaitForSingleObject(hEvent, 0))
{
// hEvent是非激活状态,也就是说另一个线程的Wait得到了hEvent,那么激活hEvent
SetEvent(hEvent);
// 跳出作别的去吧
break;
}
else
{
// hEvent 被本线程的Wait得到,也就是说另一个线程没机会得到,那么SetEvent(hEvent)并等待一段时间,直到
// 另一线程得到hEvent;此过程不断循环,可视具体情况而定
SetEvent(hEvent);
Sleep(10);
}
}

#6


我觉得是这样:你每次调用SetEvent,必须立即被另一个线程wait到才起作用,否则你下次执行SetEvent,就相当于给一个BOOL变量连续赋两次TRUE,跟一次效果一样。所以我怀疑你的测试结果,如果是连续100次调用,竟然有99次被wait到,也就是说发生了99次线程切换,有这么巧的事吗?每次需要wait的时侯都切好切换过去。

#7


事件,信号量,只是信号而已跟次数没关系吧。

#8


用两个event来做

#9


   问题找到了,主要感谢yxz_lp
   yxz_lp 说的对,"如果是单个线程等待自复位的信号量,不会存在上述问题".
   是我程序有问题: 在100次SetEvent之后,我进行一次性记数(nCount+=100),实际上在我进行,
记数之前,已经有WaitForSingleObject激活了(进行nCount--),而这时候nCount+=100还没有执行呢.
   我修改为每执行SetEvent一次,即刻对nCount变量进行保护下进行nCount++,就没有问题了.
   非常感谢大家的支持.

#1


首先我也想知道在不使用WaitForSingleObject这类API的前提下如何检测Event的状态,
其次LZ看看在_beginthreadex的时候线程初始化状态为挂起or运行?

#2


如果是单个线程等待自复位的信号量,因该不会出现上述问题,你把代码贴出来才好分析。

#3


不使用等待函数是无法检测事件状态的

#4


SetEvent 100次并不代表WaitForSingleObject会激活100次。

#5


如果你的本意是一个事件激发一次一个线程的wait,以执行某一段代码,最后使得事件数和执行代码数一直,可以用如下方法,响应事件的处理代码:


//事件来临,则
while (TRUE)
{
if (WAIT_TIMEOUT == WaitForSingleObject(hEvent, 0))
{
// hEvent是非激活状态,也就是说另一个线程的Wait得到了hEvent,那么激活hEvent
SetEvent(hEvent);
// 跳出作别的去吧
break;
}
else
{
// hEvent 被本线程的Wait得到,也就是说另一个线程没机会得到,那么SetEvent(hEvent)并等待一段时间,直到
// 另一线程得到hEvent;此过程不断循环,可视具体情况而定
SetEvent(hEvent);
Sleep(10);
}
}

#6


我觉得是这样:你每次调用SetEvent,必须立即被另一个线程wait到才起作用,否则你下次执行SetEvent,就相当于给一个BOOL变量连续赋两次TRUE,跟一次效果一样。所以我怀疑你的测试结果,如果是连续100次调用,竟然有99次被wait到,也就是说发生了99次线程切换,有这么巧的事吗?每次需要wait的时侯都切好切换过去。

#7


事件,信号量,只是信号而已跟次数没关系吧。

#8


用两个event来做

#9


   问题找到了,主要感谢yxz_lp
   yxz_lp 说的对,"如果是单个线程等待自复位的信号量,不会存在上述问题".
   是我程序有问题: 在100次SetEvent之后,我进行一次性记数(nCount+=100),实际上在我进行,
记数之前,已经有WaitForSingleObject激活了(进行nCount--),而这时候nCount+=100还没有执行呢.
   我修改为每执行SetEvent一次,即刻对nCount变量进行保护下进行nCount++,就没有问题了.
   非常感谢大家的支持.