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 的情况下被调用

C++多线程同步技巧--- 事件

MyEvent.SetEvent; // 同步信号置位

单个 SetEvent() 能否触发多个 WaitForSingleObject()

CreateEvent和SetEvent及WaitForSingleObject的使用方法

linux下怎样实现WaitForSingleObject的功能