Assertion Error with DoModal(), activated from a thread
hi, as with the topic, i am a newbie at MFC programming and ii am having trouble with DoModal
it shows the window but immediately give an assertion error
here's how the application init looks like:
over here, time_stop_dlg is a class derived from CDialog, without any changes, but has been linked to IDD_MY_DIALOG_TO_SHOW (as suggested by classwizard)
m_pMainWnd = &dlg;
AfxBeginThread ( th_start_accept, (LPVOID)this );
this is the thread procedure:
process_received_msg(buffer) is a function member of CAsevApp
UINT CAsevApp::th_start_accept( LPVOID lpvParam )
CAsevApp *th_start_accept = (CAsevApp*)lpvParam;
void CAsevApp::process_received_msg(char *msg)
time_stop_dlg_obj.DoModal(); // NIGHTMARE BEGINS HERE!
a snippet of wincore assertion error:
BOOL PASCAL CWnd::WalkPreTranslateTree(HWND hWndStop, MSG* pMsg)
ASSERT(hWndStop == NULL || ::IsWindow(hWndStop));
ASSERT(pMsg != NULL);
// walk from the target window up to the hWndStop window checking
// if any window wants to translate this message
for (HWND hWnd = pMsg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd))
CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
if (pWnd != NULL)
// target window is a C++ window
return TRUE; // trapped by target window (eg: accelerators)
// got to hWndStop window without interest
if (hWnd == hWndStop)
return FALSE; // no special processing
your assistance please! :WAVE:
MFC window objects are not thread safe, AFAIK MFC uses thread local storage. Do never access MFC window objects (including controls) created by one thread in another thread.
You can work around this problem (sometimes), if you *must* using critical sections, volatile variables, and whatnot to ensure only one thread is touching a mfc object at any one time but in general try not to design code that needs this. The problem is a lot of the automatic windows stuff can't be wrapped on your end in a critical section, so sometimes the problem can't be fixed at all.
AFAIK this is not true. I just looked up the issue to brush up my knowledge: The handle maps internally used by the MFC are thread global. You generally cannot pass CWnd (/derived) objects between threads.
Originally Posted by jonnin
If you need a CWnd object in another thread, just pass its handle and call CWnd::FromHandle(HWND) to get a temporary CWnd object for the referenced window. Be warned that (a) this object is temporary and (b) it is a pointer to a CWnd, not to a derived class.
Let me further explain the importance of (b) for short: You can get a CWnd* from a HWND and (reinterpret) cast it to a derived class, e.g.
You can successfully call CWnd functions on pWndDerived. You can successfully call CWndDerived functions on pWndDerived that just use the wrapped windows handle to send functions to the window, for example. But you cannot call (for example) a function that uses data members specific to the CWndDerived class. Most of the time, you won't do so or need it, anyway.
CWndDerived * pWndDerived = reinterpret_cast<CWndDerived*>(CWnd::FromHandle(hWnd));
Also, note that you do not need to synchronize sending windows messages using the HWND. A window has only one message queue and thus can process messages only sequentially.
-- Android Development Center
-- Cloud Development Project Center
-- HTML5 Development Center
-- Windows Mobile Development Center