Windows:在什么情况下SetEvent()不会立即返回?

时间:2008-11-21 23:32:46

标签: windows

我有一个线程,当它的函数退出其循环(退出由事件触发)时,它会进行一些清理,然后设置一个不同的事件让主线程知道它已完成。

但是,在某些情况下,SetEvent()在设置线程的“我已完成”事件后似乎不会返回。

此线程是DLL的一部分,问题似乎发生在DLL加载/附加,线程启动,线程结束以及DLL分离/卸载多次之后,应用程序之间没有关闭。在此问题发生之前必须重复此序列的次数是可变的。

如果你怀疑我知道我在说什么,我已经通过调用OutputDebugString()包围了SetEvent()调用来确定发生了什么。出现SetEvent()之前的输出。然后,等待线程产生输出,指示事件已被设置。

但是,在退出线程(一个AFTER SetEvent())中对OutputDebugString()的第二次调用永远不会发生,或者至少它的字符串永远不会出现。如果发生这种情况,应用程序会在几分钟后崩溃。

(请注意,在问题开始发生后添加了对OutputDebugString()的调用,因此它不可能挂在那里,而不是挂在SetEvent()中。)

我不完全确定导致崩溃的原因,但是它发生在SetEvent()没有立即返回的同一个线程中(我一直在跟踪/输出线程ID)。我想SetEvent()最终可能会返回,到那时它返回的上下文已经/无效,但是什么可能导致这样的延迟?

事实证明,我已经被这段代码看了很长时间,而且我甚至没有检查返回代码。我已经完成了今天的工作,所以我知道周一它会返回什么(如果它正在返回),我将用这些信息编辑这个问题。

更新:我更改了(主)代码以等待线程退出而不是设置事件,并从从属线程中删除了SetEvent()调用。这改变了bug的性质:现在,它不会从SetEvent()返回,而是根本不退出线程,整个事情都会挂起。

这表明问题不在于SetEvent(),而在于更深层次的问题。不知道是什么,但是不要追逐那条死胡同是好的。

更新(2009年2月13日):
事实证明,当我问这个问题时,问题比我想象的要深。 jdigital(可能还有其他人)几乎已经解决了潜在的问题:我们试图在分离DLL的过程中卸载一个线程。

正如我当时没有意识到的那样,但此后通过研究和其他地方(例如Raymond Chen的博客)发现,这是一件非常糟糕的事情。

问题在于,由于它的编码方式和行为方式,这不是显而易见的,这是潜在的问题 - 它被伪装成各种其他不良行为,我不得不趟过。

这里的一些建议帮助我做到了,所以我很感谢所有贡献的人。谢谢!

4 个答案:

答案 0 :(得分:2)

您是否取消HANDLE *传递给SetEvent?事件句柄引用更可能是无效的,并且崩溃是访问冲突(即访问垃圾)。

答案 1 :(得分:1)

谁正在卸载DLL并在卸载的什么时候完成?我想知道在线程运行完成之前是否存在卸载DLL的时间问题。

答案 2 :(得分:0)

您可能希望使用WinDbg来捕获崩溃并检查堆栈。

答案 3 :(得分:0)

为什么需要在从属线程中设置一个事件来触发线程完成的主线程?只要退出线程,调用主线程应该等待工作线程退出,例如伪代码 -

Master
{
   TerminateEvent = CreateEvent ( ... ) ;
   ThreadHandle = BeginThread ( Slave, (LPVOID) TerminateEvent ) ;
   ...
   Do some work
   ...
   SetEvent ( TerminateEvent ) ;
   WaitForSingleObject ( ThreadHandle, SOME_TIME_OUT ) ;
   CloseHandle ( TerminateEvent ) ;
   CloseHandle ( ThreadHandle ) ; 
}

Slave ( LPVOID ThreadParam )
{
   TerminateEvent = (HANDLE) ThreadParam ;
   while ( WaitForSingleObject ( TerminateEvent, SOME__SHORT_TIME_OUT ) == WAIT_TIMEOUT )
   { 
      ... 
      Do some work 
      ...
   }
}

要检查有很多错误条件和状态,但这是我通常的做法的本质。

如果你能掌握它,拿到这本书,它在很多年前我第一次阅读它的时候改变了我对Windows开发的生活。

Advanced Windows: The Developer's Guide to the Win32 Api for Windows Nt 3.5 and Windows 95 (Paperback), by Jeffrey Richter (Author)