Windows setevent 处理
Posted
技术标签:
【中文标题】Windows setevent 处理【英文标题】:Windows setevent processing 【发布时间】:2013-10-17 12:09:34 【问题描述】:我想知道如何在 Windows 内部处理 setevent。
我有以下情况
在 std::atomic == true 时执行的 Std::thread 线程循环 循环内部是一个 waitforsingleObject,它在警报状态下无限休眠。
一个函数 stopThread() 执行以下操作: - 清除原子布尔值 - 在事件对象上调用 Setevent - 调用thread.join
这个经常挂,我感觉setevent在当前线程还有一些工作要做,而join块 当前线程。
如果我在 waitforsinlgleObject 之后设置的线程中添加一个额外的布尔值,并且我在调用 join() 之前等待它被设置 一切似乎都正常。
代码(此处省略错误检查)
初始化代码/声明:
HANDLE m_WakeupThreadEvent;
std::atomic<bool> m_ReceiverEnabled;
m_WakeupThreadEvent = CreateEvent(NULL, false, false, "RxThreadWakeupEvent" );
线程代码:
while(m_ReceiverEnabled)
DWORD rslt = WaitForSingleObjectEx(m_WakeupThreadEvent, INFINITE, true);
// Here some checking for rslt;
功能代码:
m_ReceiverEnabled = true;
SetEvent( m_WakeupThreadEvent )
m_Thread.join()
对这种行为有什么解释吗?我找不到有关 setEvent() 操作的任何详细信息
【问题讨论】:
请同时显示您的代码,简化为线程部分。我希望您有一个竞争条件:在您触发事件时,线程已检查std::atomic
但尚未开始等待,并且您正在使用自动重置事件。
我添加了代码。我不希望出现比赛条件。我发生在线程持续休眠的“被动状态”,所以不检查布尔值。
请包括事件的创建和m_ReceiverEnabled
的声明
它肯定挂在 WFSOE 上?在当时恰好处理的某些排队的 APC 完成例程中没有?
我在完成例程的早期放了一个 return,所以没有执行重要的代码。还在WFSO语句后面加了一个断点,好像没有达到。只有 setEvent 和 Join 之间的延迟似乎有帮助。
【参考方案1】:
我刚刚注意到一件事:为什么将m_ReceiverEnabled
设置为true
?它应该设置为false
。我已经在下面的代码中做到了这一点。
即使您确定竞态条件不是问题的根源,由于使用了自动重置事件,您仍然会遇到竞态条件。你能解决它,然后看看这是否也能解决你的主要问题?这是使用手动重置事件而不是无竞争方式的代码:
HANDLE m_WakeupThreadEvent;
std::atomic<bool> m_ReceiverEnabled;
m_WakeupThreadEvent = CreateEvent(NULL, TRUE, FALSE, "RxThreadWakeupEvent" );
m_ReceiverEnabled = false;
SetEvent( m_WakeupThreadEvent )
m_Thread.join()
while(true)
DWORD rslt = WaitForSingleObjectEx(m_WakeupThreadEvent, INFINITE, true);
ResetEvent(m_WakeupThreadEvent);
if(!m_ReceiverEnabled)
break;
// Here some checking for rslt;
【讨论】:
将其更改为手动重置事件似乎可以解决问题。唯一我不明白的是,自动重置事件是如何产生竞争条件的。 线程必须在脉冲时主动等待自动重置事件,否则脉冲将丢失。我想你的线程不是,要么是因为事件已经被触发,因此在 while 循环中的某个地方,要么是因为你在 APC 中。以上是关于Windows setevent 处理的主要内容,如果未能解决你的问题,请参考以下文章
setEvent 在没有 ResetEvent 的情况下被调用
单个 SetEvent() 能否触发多个 WaitForSingleObject()