Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ WaitForSingleObject()_C++_Multithreading_Winapi - Fatal编程技术网

C++ WaitForSingleObject()

C++ WaitForSingleObject(),c++,multithreading,winapi,C++,Multithreading,Winapi,我陷入了一个非常惊人的问题,代码如下 class A { public: A(){ m_event = CreateEvent(NULL, false, false, NULL); // create an event with initial value as non-signalled m_thread = _beginthread(StaticThreadEntry, 0, this); // create a t

我陷入了一个非常惊人的问题,代码如下

class A
{
   public:  
   A(){  
         m_event =  CreateEvent(NULL, false, false, NULL);       // create an event with initial value as non-signalled
         m_thread = _beginthread(StaticThreadEntry, 0, this);    // create a thread 
      }

   static void StaticThreadEntry(A *  obj) {  obj->ThreadEntry();  }

   void ThreadEntry();
};

void A::ThreadEntry()
{
     WaitforSingleObject(m_event,INFINITE);
}


int main()
{
        A a;

        SetEvent(m_event);     // sets the event to signalled state which causes the running thread to terminate 

        WaitForSingleObject(m_thread, INFINITE);  // waits for the thread to terminate

        return 0;
 } 
问题:

当上面的代码运行时,有时(五分之一)会挂起,并且控件在调用WaitforSingleObject()时(在主函数内部)会卡住。代码始终调用SetEvent()函数,以确保线程在调用Wait()函数之前终止


我看不出它为什么会挂起?

我看不出代码中有任何问题(假设事件是在构造函数中启动线程之前创建的)

  • 该事件是一个自动重置事件,并且 初始状态为无信号状态
  • 子线程必须等到 事件发出信号
  • 主线程将向事件发送信号,然后 等待子进程终止
假设这是完整的代码(不是示例代码),我觉得它很好

我建议你用它来观察事件的状态

编辑

在主线程等待线程句柄之前,子线程很可能会终止。如果句柄被其他内核对象重用,主线程将无限等待。
尝试在创建线程后使用复制句柄,并在WaitForSingleObject中使用此句柄

> P>您可能想考虑使用替代的<<代码> SETEVER()/<代码>和<代码> WaIfFutSunLobObjor()/Case>调用,因为这是作为单个操作发生的,如果无法发出信号,则会立即失败。 您是否检查了线程句柄m_线程是否实际有效

在某些情况下,_beginthread将返回无效句柄-特别是当线程快速退出时(这里肯定是这种情况,因为线程可能会旋转,通过等待(因为事件已经设置),然后终止)


使用_beginthreadex来创建句柄,尽管您必须调用_endthreadex以确保所有内容都已清理。

问题在于您使用了_BeginThreadAPI。不能将此函数返回的句柄与Win32 wait函数一起使用。您应该使用_beginthreadex或CreateThread。从MSDN:

如果成功,这些函数中的每一个都会向新创建的线程返回一个句柄;但是,如果新创建的线程退出得太快,_beginthread可能不会返回有效的句柄

你是。。。能够将_beginthreadex返回的线程句柄与同步API一起使用,这是_beginthread无法做到的


如果在线程中的
WaitforSingleObject
之前执行
SetEvent
,则线程将挂起。因此,在这种情况下,
WaitforSingleObject(m_event,INFINITE)
将永远等待。

在对象完全构造之前分发对象的地址是否是一种好的做法。我们可以控制新线程何时执行
obj->ThreadEntry()
,它可能是在构造函数完成之后,有一个完整的对象可以调用ThreadEntry,或者ThreadEntry可能是在对象被构造之前开始的。

Hasturkun说这是一个原子操作

然而,MSDN不同意:

请注意,“信号”和“等待”是 不保证作为一个整体执行 原子操作。在上执行的线程 其他处理器可以观察到 第一个对象的信号状态 在线程调用之前 SignalObjectAndWait开始等待 第二个对象


是的,我自己也有点困惑,我的头现在很痛,但我相信我会找到答案的。它可能不是原子的,但它似乎表明,它完成了确保线程在对象发出信号之前等待对象的任务。对吗?

我很抱歉,人们-所有的答案似乎都错了。我使用Sleep()尝试了代码中的所有组合,我认为它没有理由挂起?为什么不按m_event=Create排序。。。那么_beginthread?如果问题中的代码不正确,您需要对其进行编辑-许多人都指出了一个错误,而您在评论中说的错误并不存在。现在我很困惑,所以没办法。你为什么不编译你的例子,看看它是否再现了这个问题?在我看来,事实并非如此。这段代码没有什么问题,除了m_事件/m_线程作用域,我认为这只是您在示例中遗漏的一部分。当问这类问题时,几乎总是需要发布可编译代码来重新处理问题。通常很难诊断与时间相关的bug——为什么要把它变成猜测游戏呢?如果你不能发布真正的代码(因为它太复杂,有太多的依赖项,或者是专有的),那么将它缩减到一个小的复制案例通常会有一个额外的好处,让你看到问题,所以你甚至不需要发布问题。是的,事件是在创建线程之前构建的。是的,正如你所说的,这段代码很好。上面的答案没有任何意义。你能编辑有问题的代码以反映事件创建的顺序吗?当Windows试图重用句柄值时,句柄复制是很有可能的。不要使用_beginthread,而是使用_beginthreadex。这样,您将负责关闭手柄。(等待后需要关闭句柄,然后使用CloseHandle)如果句柄关闭得太快,无法调用WaitForSingleObject,那么它也关闭得太快,无法调用DuplicateHandle。显然,一旦函数返回,_beginthread的返回值就可能过时。(为什么会这样写?)是的,我可以试试这个。谢谢。注意“信号”和“等待”不能保证作为原子操作执行。在其他处理器上执行的线程可以在调用SignalObjectAndWait的线程开始对第二个对象进行等待之前观察第一个对象的信号状态。@TripleS:您是正确的。在我回答这个问题时,MSDN页面描述了这一点