C++ WaitForSingleObject()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/964719/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WaitForSingleObject( )
提问by Rakesh Agarwal
I have got myself stuck into a really amazing issue here.The code is like as below.
我在这里陷入了一个非常惊人的问题。代码如下。
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;
}
Problem :
问题 :
When the above code is run,sometimes( 1 out of 5 ) it hangs and the control gets stuck in the call to WaitforSingleObject()( inside the main function ).The code always calls SetEvent() function to ensure that the thread would terminate before calling Wait() function.
当上面的代码运行时,有时(5 个中的 1 个)它挂起并且控制卡在对 WaitforSingleObject() 的调用中(在 main 函数内部)。代码总是调用 SetEvent() 函数以确保线程将终止在调用 Wait() 函数之前。
I do not see any reason why it should ever hang?
我看不出它应该挂起的任何理由?
回答by Peter Ruderman
The problem is your use of the _beginthread API. You cannot use the handle returned from this function with the Win32 wait functions. You should use _beginthreadex or CreateThread. From MSDN:
问题在于您使用了 _beginthread API。不能将此函数返回的句柄与 Win32 等待函数一起使用。您应该使用 _beginthreadex 或 CreateThread。来自 MSDN:
If successful, each of these functions returns a handle to the newly created thread; however, if the newly created thread exits too quickly, _beginthread might not return a valid handle...
You are ... able to use the thread handle returned by _beginthreadex with the synchronization APIs, which you cannot do with _beginthread.
如果成功,这些函数中的每一个都会返回一个新创建线程的句柄;但是,如果新创建的线程退出得太快,_beginthread 可能不会返回有效的句柄...
您可以……能够将 _beginthreadex 返回的线程句柄与同步 API 一起使用,而 _beginthread 则无法做到这一点。
回答by aJ.
I don't see any issues in the code (Assuming event is created before the thread is started in constructor).
我在代码中没有看到任何问题(假设在构造函数中启动线程之前创建了事件)。
- The event is a auto reset event and the initial state is non signaled.
- Child thread has to wait until the event is signaled.
- Main thread will signal the event and waits for child process to terminate.
- 该事件是一个自动重置事件,初始状态没有信号。
- 子线程必须等到事件发出信号。
- 主线程将发出事件信号并等待子进程终止。
Assuming this is the complete code (not the sample code ), it looks quite fine to me.
假设这是完整的代码(不是示例代码),对我来说它看起来很不错。
I suggest you to use process Explorerto observe the state of the event.
我建议您使用流程资源管理器来观察事件的状态。
EDIT:
编辑:
There is a slight chance that child thread gets terminated before the main thread waits on the thread handle. If the handle is reused for some other kernel objects and main thread will wait infinitely. Try duplicating the handle using DuplicateHandleafter thread creation and use this handle in WaitForSingleObject.
在主线程等待线程句柄之前,子线程有可能被终止。如果句柄被其他一些内核对象重用,主线程将无限等待。尝试在线程创建后使用DuplicateHandle 复制句柄,并在 WaitForSingleObject 中使用此句柄。
回答by Hasturkun
you might want to consider using SignalObjectAndWaitinstead of the seperate SetEvent()
and WaitForSingleObject()
calls, as this occurs as a single operation, and would fail immediately if the event could not be signaled.
您可能需要考虑使用SignalObjectAndWait而不是单独的SetEvent()
和WaitForSingleObject()
调用,因为这是作为单个操作发生的,如果无法发出事件信号,则会立即失败。
回答by Alan Moore
Have you checked whether the thread handle m_thread is actually valid?
您是否检查过线程句柄 m_thread 是否实际有效?
There are circumstances where _beginthread will return an invalid handle - particularly when the thread exits quickly (which certainly could be the case here as the thread could spin up, pass through the wait (as the event is already set) and then terminate).
在某些情况下 _beginthread 将返回无效句柄 - 特别是当线程快速退出时(这当然可能是这种情况,因为线程可能会旋转,通过等待(因为事件已经设置)然后终止)。
Use _beginthreadex instead to create the handle, although you would have to call _endthreadex to make sure everything was cleaned up.
使用 _beginthreadex 来创建句柄,尽管您必须调用 _endthreadex 以确保所有内容都已清除。
回答by Test
The thread will hang if SetEvent
executes before WaitforSingleObject
in the thread. So in that case WaitforSingleObject(m_event,INFINITE)
will wait forever.
如果在线程中SetEvent
之前执行,线程将挂起WaitforSingleObject
。所以在那种情况下WaitforSingleObject(m_event,INFINITE)
会永远等待。
回答by martsbradley
Is it not bad practice to hand out the address of an object prior to that object being fully constructed. We have control of when the new thread will execute obj->ThreadEntry()
, it may be after the constructor has completed, there is a full object on which to call ThreadEntry, or ThreadEntry may begin prior to the object being constructed.
在完全构造对象之前分发对象的地址是不是不好的做法。我们可以控制新线程何时执行obj->ThreadEntry()
,可能是在构造函数完成后,有一个完整的对象可以调用 ThreadEntry,或者 ThreadEntry 可能在对象被构造之前开始。
回答by MarkS
Hasturkun says that SignalObjectAndWaitis an atomic operation.
Hasturkun 说SignalObjectAndWait是一个原子操作。
However, MSDN disagrees:
但是,MSDN 不同意:
Note that the "signal" and "wait" are not guaranteed to be performed as an atomic operation. Threads executing on other processors can observe the signaled state of the first object before the thread calling SignalObjectAndWait begins its wait on the second object.
请注意,“信号”和“等待”不能保证作为原子操作执行。在其他处理器上执行的线程可以在调用 SignalObjectAndWait 的线程开始等待第二个对象之前观察第一个对象的信号状态。
Ya, I'm a little confused myself and my head hurts right now, but I'm sure I'll figure it out. It may not be atomic, but it appears to say that it accomplishes making sure that your thread is waiting on the object before the object to be signaled is signaled. Right?
是的,我自己有点困惑,现在我的头很痛,但我相信我会弄清楚的。它可能不是原子的,但它似乎表明它可以确保您的线程在要发出信号的对象发出信号之前正在等待该对象。对?