2010-12-22 193 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