我正在用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
MultiThread功能
...
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,就不会有死锁。如果我在按下关闭按钮之前让线程查看最顶层,也没有问题。那死为什么呢?
答案 0 :(得分:1)
UpdateWindow()函数只能在拥有该窗口的线程调度WM_PAINT事件之前完成。这不可能发生,在WaitForSingleObject调用中阻止了UI线程。该调用永远无法完成,该线程在UpdateWindow上被阻止。死锁。
如果您没有通过用户界面观察线程冷酷的严格规则,那么此类代码将会让您活着。 user32和gdi都不是线程安全的。 UI线程可以从不阻止而不会消息。您必须使用MsgWaitForMultipleObjectsEx()。工作线程永远不会直接使用影响窗口的任何API函数。只有系统消息被自动封送,使用PostMessage()代替,以便UI线程可以进行更新。
答案 1 :(得分:0)
我不知道UpdateWindow一直在等待WM_PAINT。我猜InvalidateRect即使不等待WM_PAINT也不是线程安全的。我改变了我的工作线程以使用PostMessage。谢谢!