前言:
试想这样一种场景:
子线程通过SendMessage同步消息到主线程,假设子线程的结束是通过标志位来控制的。当主线程想要尝试结束子线程的时候
一般是这样操作的,
bFlag = false;
WaitForSingleObject(hThread,INFINITE); //阻塞等待
CloseHandle(hThread);
将标志位置为false后,在子线程的主循环中肯定会判断,false将会退出,假设当主线程执行了WaitForSingleObject后,
子线程恰好执行到了SendMessage函数,SendMessage本身就是阻塞的,需要等到主线程回应才继续往下执行。
这便造成了死锁——主线程等子线程结束,子线程等主线程执行同步,相互等待。
解决方案
处理方法有很多,比如:
1、子线程改用PostMessage();
2、主线程改用MsgWaitForMultipleObjects();
但是有一些场景是不能用PostMessage的,例子就不举了,说一下第二种方案,实现代码如下:
while(true)
{
if(WAIT_OBJECT_0 == MsgWaitForMultipleObjects(1,&m_hThread,false,INFINITE,QS_ALLINPUT))
{
break;
}
else
{
if(PeekMessage(&mymsg,m_hWnd,0,0,PM_REMOVE))
{
TranslateMessage(&mymsg);
DispatchMessage(&mymsg);
}
}
}
CloseHandle(m_hThread);
这样做可以让主线程既等待子线程,又可以处理消息,不至于子线程SendMessage时导致死锁。
注意
这样会使程序是非阻塞的,比如按钮点了又可以点,处理要小心一点。比如有个按钮功能是停止线程,用户点了又可以点,最好能让按钮失效。