Индикатор выполнения в пользовательском интерфейсе MFC заблокирован - PullRequest
0 голосов
/ 02 ноября 2011

Для работы проекта MFC мне нужно создать диалоговое окно индикатора выполнения (CProgressCtrl) в отдельном потоке пользовательского интерфейса (CWinThread).Я взял пример с сайта http://adilevin.wordpress.com/2009/06/29/user-interface-threads-in-mfc/.Работает сам по себе.(В основном, он имеет два индикатора выполнения, один из основного потока графического интерфейса, другой, созданный в отдельном потоке пользовательского интерфейса. Пример продемонстрировал, что вычисления, выполняемые в основном потоке пользовательского интерфейса, не нарушают индикатор выполнения, созданный в пользовательском потоке)

Но когда я поместил код в мое приложение, индикатор выполнения застрял в вызове SetPos для CProgressCtrl.Когда я замораживаю основной поток (пока он выполняет вычисления), я получаю сообщение от Visual Studio

Процесс, кажется, заблокирован (или не выполняется какой-либо код пользовательского режима).Все потоки были остановлены.

, поэтому кажется, что UI-поток ожидает чего-то из основного потока?Но я понятия не имею, чего он ждет.Вот стек вызовов пользовательского потока, в котором он застрял.

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++

Кто-нибудь знает, что не так?

Когда я запускаю пример приложения самостоятельно, онне делает звонки uxtheme.dll, потому что он не используется в образце.Может ли последний SendMessageW быть проблемой?

1 Ответ

1 голос
/ 02 ноября 2011

SetPos подразумевает вызов на SendMessage, который является блокирующим вызовом. Вы должны никогда вызывать SendMessage через границу потока, поскольку это обречено на взаимоблокировку.

Если вам нужно обновить GUI, работающий в главном потоке, вы должны использовать PostMessage:

PostMessage(hWndMain, UWM_MYMESSAGE, progress, 0);

И обработать сообщение в основном потоке:

LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam)
{
   m_progress.SetPos((int)wParam);
   return 1;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...