Reputation: 726
For a MFC project at work, I have to create a progress bar dialog (CProgressCtrl) in a separate UI thread (CWinThread). I took the example from the site http://adilevin.wordpress.com/2009/06/29/user-interface-threads-in-mfc/ . It works on its own. (Basically, it has two progress bars, one from the main gui thread, one created in a separate ui thread. The example demonstrated that computation performed in the main gui thread does not disturb the progress bar created in the ui thread)
But when I put the code in my application, the progress bar got stuck in the SetPos call to the CProgressCtrl. When I freeze the main thread (while it's running computation), i get the message from Visual Studio
The process appears to be deadlocked (or is not running any user-mode code). All threads have been stopped.
so it seems like the UI-thread is waiting for something from main thread? But I have no idea what it is waiting for. Here is the call stack of the ui-thread where it get stuck.
user32.dll!GetPropW() + 0x72 bytes
[Frames below may be incorrect and/or missing, no symbols loaded for user32.dll]
user32.dll!SendMessageW() + 0x4c bytes
uxtheme.dll!DrawThemeParentBackgroundEx() + 0x114 bytes
comctl32.dll!GetEffectiveClientRect() + 0x28f0 bytes
comctl32.dll!GetEffectiveClientRect() + 0x2916 bytes
comctl32.dll!GetEffectiveClientRect() + 0x2af3 bytes
comctl32.dll!GetEffectiveClientRect() + 0x2a25 bytes
comctl32.dll!GetEffectiveClientRect() + 0x2992 bytes
user32.dll!gapfnScSendMessage() + 0x270 bytes
user32.dll!gapfnScSendMessage() + 0x922 bytes
user32.dll!FillRect() + 0x110 bytes
user32.dll!CallWindowProcA() + 0x1b bytes
mfc100d.dll!CWnd::DefWindowProcA(unsigned int nMsg=15, unsigned int wParam=0, long lParam=0) Line 1089 + 0x20 bytes C++
mfc100d.dll!CWnd::WindowProc(unsigned int message=15, unsigned int wParam=0, long lParam=0) Line 2088 + 0x1c bytes C++
mfc100d.dll!AfxCallWndProc(CWnd * pWnd=0x08156d68, HWND__ * hWnd=0x00012452, unsigned int nMsg=15, unsigned int wParam=0, long lParam=0) Line 257 + 0x1c bytes C++
mfc100d.dll!AfxWndProc(HWND__ * hWnd=0x00012452, unsigned int nMsg=15, unsigned int wParam=0, long lParam=0) Line 420 C++
cv32.dll!AfxWndProcDllStatic(HWND__ * hWnd=0x00012452, unsigned int nMsg=15, unsigned int wParam=0, long lParam=0) Line 54 + 0x15 bytes C++
user32.dll!gapfnScSendMessage() + 0x270 bytes
user32.dll!GetDC() + 0x52 bytes
user32.dll!GetWindowLongW() + 0x18a bytes
user32.dll!GetDC() + 0xab bytes
ntdll.dll!KiUserCallbackDispatcher() + 0x2e bytes
comctl32.dll!GetEffectiveClientRect() + 0x2660 bytes
comctl32.dll!RegisterClassNameW() + 0x37e bytes
user32.dll!gapfnScSendMessage() + 0x270 bytes
user32.dll!gapfnScSendMessage() + 0x922 bytes
user32.dll!FillRect() + 0x110 bytes
user32.dll!CallWindowProcA() + 0x1b bytes
mfc100d.dll!CWnd::DefWindowProcA(unsigned int nMsg=1026, unsigned int wParam=65, long lParam=0) Line 1089 + 0x20 bytes C++
mfc100d.dll!CWnd::WindowProc(unsigned int message=1026, unsigned int wParam=65, long lParam=0) Line 2088 + 0x1c bytes C++
mfc100d.dll!AfxCallWndProc(CWnd * pWnd=0x08156d68, HWND__ * hWnd=0x00012452, unsigned int nMsg=1026, unsigned int wParam=65, long lParam=0) Line 257 + 0x1c bytes C++
mfc100d.dll!AfxWndProc(HWND__ * hWnd=0x00012452, unsigned int nMsg=1026, unsigned int wParam=65, long lParam=0) Line 420 C++
cv32.dll!AfxWndProcDllStatic(HWND__ * hWnd=0x00012452, unsigned int nMsg=1026, unsigned int wParam=65, long lParam=0) Line 54 + 0x15 bytes C++
user32.dll!gapfnScSendMessage() + 0x270 bytes
user32.dll!gapfnScSendMessage() + 0x922 bytes
user32.dll!GetWindow() + 0x21a bytes
user32.dll!SendMessageA() + 0x4c bytes
mfc100d.dll!CProgressCtrl::SetPos(int nPos=65) Line 363 + 0x46 bytes C++
cv32.dll!CProgressCtrlWithTimer::OnTimer(unsigned int nIDEvent=1) Line 1577 C++
Anyone has any clue on what is wrong?
When I run the sample application on its own, it doesn't make calls to uxtheme.dll because it is not being used in the sample. Could the last SendMessageW be the problem?
Upvotes: 0
Views: 7152
Reputation: 19937
SetPos
implies a call to SendMessage
which is a blocking call. You must never call SendMessage
across thread boundary as this is doomed to cause deadlocks.
If you need to update the GUI running on the main thread, you must use PostMessage
:
PostMessage(hWndMain, UWM_MYMESSAGE, progress, 0);
And handle the message in the main-thread:
LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam)
{
m_progress.SetPos((int)wParam);
return 1;
}
Upvotes: 1