线程死锁

来源:互联网 发布:淘宝上的pvc地板好不好 编辑:程序博客网 时间:2024/04/28 06:15

你在主线程用了WaitForSingleObject,导致了消息循环的阻塞,界面假死。然后在线程中调用了SetDlgItemText,而SetDlgItemText实际上调用的是SendMessage,而SendMessage要等待主线程处理完毕发送的消息才返回继续执行,而你主线程的消息循环已经阻塞,无法处理消息,导致整个过程“我等你,你等我”,无穷下去

在界面线程不能使用Sleep和WaitForSingleObject之类的函数,比较好的方法是,将句柄作为线程参数传递进线程,当线程结束后发一条消息通知主线程处理完毕




编译器的最优化又可能导致这个问题,使用volatile修饰一下bTerminate
  在整个循环过程中(while (!bTerminate) { })bTerminate会被放入CPU的寄存器中,每次
  while做判断的时候读取的都是寄存器中的值,即使你在程序中改变了bTerminate为TRUE,
  由于最优化的缘故,while循环不会退出,导致线程就象死了一样!也是一种可能!


问题描述:AfxBeginThread创建一个线程后,在线程中操作UI的控件,例如EDIT。在UI的button里停止线程,并等待结束,一般用WaitforsingleObject,但是这个函数会导致UI消息阻塞,如果这个时候线程里正好操作UI控件并需要用到SendMessage,则线程在等待消息发送完,WaitforsingleObject在等待线程,而WaitforsingleObject又阻塞了消息,这样就导致了死循环。下文为解决方法,已经省略,全部可以参考原文地址:


还可以看出:MsgWaitForMultipleObjects实际上在这其中并没有起到什么实质性的作用,只是定期返回而已,那么根据此,可以用固定时间的WaitForSingleObject来代替MsgWaitForMultipleObjects,并且循环等待 ;同时,我们也没有必要手动DispatchMessage,只需要PeekMessage即可,需要注意的是如果删除了DispatchMessage,PeekMessage时不能将消息从队列取走。代码如下:


[cpp] view plaincopy
  1. DWORD dwRet = 0;    
  2. MSG msg;    
  3. while (TRUE)    
  4. {    
  5.   dwRet = WaitForSingleObject(m_hThread, 50);    
  6.   switch(dwRet)    
  7.   {    
  8.   case WAIT_OBJECT_0:     
  9.     break//break the loop    
  10.   case WAIT_TIMEOUT :    
  11.     PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);    
  12.     continue;    
  13.   default:    
  14.     break// unexpected failure    
  15.   }    
  16.   break;    
  17. }    

      经过测试,代码运行正确!


      当然,由于MsgWaitForMultipleObjects是基于消息驱动的返回,WaitForSingleObject只是普通的定时返回,而本文的情况就是由于消息阻塞造成的,所以MsgWaitForMultipleObjects比WaitForSingleObject在应用时时效性更好,如果改成WaitForSingleObject,在测试中感觉会有略为滞后,所以实际还是以MsgWaitForMultipleObjects为佳。

原创粉丝点击