2010-12-22 154 views
1

我正在用Visual C++编写基于对话框的多线程应用程序。它有几个观点。线程关闭导致的死锁

函数OnInitialUpdate我开始工作线程这样的:

pThread = AfxBeginThread(MultiThread, this, THREAD_PRIOIRITY_NORMAL, 0 CREATE_SUSPENDED, NULL); 
pThread->m_bAutoDelete = false; 
pThread->ResumeThread(); 

OnDestroy函数中我有

eventKill.SetEvent(); 
WaitForSingleObject(pHread->m_hThread, INFINITE); 
delete pThread 

多线程功能有

... 
while (WaitForSingleObject(pView->eventKill.m_hObject, 0) != WAIT_OBJECT_0) 
{ 
    ... 
    pView->InvalidateRect(rect); 
    pView->UpdateWindow(); 
    Sleep(100); 
} 
return 0; 

这通常会关闭好听,但我发现了一个例外。我有这个线程和它的视图运行。还有另外一个视图在顶部,线程视图部分位于其下。如果我通过直接按下它的关闭按钮来关闭线程视图,而不首先使该线程查看最上面的窗口,程序会在WaitForSingleObject(pThread-> m_hThread,INFINITE)中死锁。如果我不使用UpdateWindow,则不会出现死锁。如果我在按下关闭按钮之前让线程查看最顶层,那么也没有问题。那么为什么会陷入僵局?

回答

1

UpdateWindow()函数只能在拥有窗口的线程调度WM_PAINT事件之前完成。在这里不会发生,UI线程在WaitForSingleObject调用中被阻塞。该调用永远无法完成,该线程在UpdateWindow上被阻塞。僵局。

如果你没有观察到用户界面线程严格的线程规则,这种代码将会让你活着吃东西。 user32和gdi都不是线程安全的。 UI线程可以从来没有块没有泵信息。你必须使用MsgWaitForMultipleObjectsEx()。工作线程应该从永远不要直接使用任何影响窗口的API函数。只有系统消息会自动封送,请使用PostMessage(),以便UI线程可以执行更新。

+0

我学会了这个艰难的道路......像花岗岩一样坚硬。 – 2010-12-23 13:27:06

0

我不知道UpdateWindow一直在等待WM_PAINT。我猜也InvalidateRect不是线程安全的,即使它不等待WM_PAINT。我改变了我的工作线程使用PostMessage。谢谢!

+0

更好地使用评论来回复某人的回答。 :) – 2010-12-23 13:27:39