Microsoft KB Archive/177101

= BUG: An ASSERT may occur in AfxWndProc when two or more threads display modal dialog boxes in an MFC regular DLL in Visual C++ =

Article ID: 177101

Article Last Modified on 11/21/2006

-

APPLIES TO

 Microsoft Foundation Class Library 4.2, when used with:  Microsoft Visual C++ 4.2 Enterprise Edition

 Microsoft Visual C++ 5.0 Enterprise Edition

 Microsoft Visual C++ 6.0 Enterprise Edition

 Microsoft Visual C++ 4.2 Professional Edition</li></ul>

 Microsoft Visual C++ 5.0 Professional Edition</li></ul>

 Microsoft Visual C++ 6.0 Professional Edition</li></ul>

 Microsoft Visual C++ 6.0 Standard Edition</li></ul> </li></ul>

-

<div class="notice_section">

This article was previously published under Q177101

<div class="symptoms_section">

SYMPTOMS
If two or more threads display modal dialog boxes at the same time inside an MFC regular dynamic-link library (DLL) (USRDLL), the following ASSERT may be generated in AfxWndProc, on Wincore.cpp, line 365 in Visual C++ 6.0 (line 368 in Visual C++ 5.0, line 360 in Visual C++ 4.2): // All other messages route through message map. CWnd* pWnd = CWnd::FromHandlePermanent(hWnd); ASSERT(pWnd != NULL); This ASSERT occurs only if one of the threads was created outside of the DLL.

The probability of this problem occurring increases with the number of threads and modal dialog boxes.

<div class="cause_section">

CAUSE
When AfxGetThread is called in an MFC regular DLL from a secondary thread that was not created inside the DLL, it returns the CWinApp object for the DLL because a CWinThread object was not created for the thread in the context of the DLL.

When a modal dialog box is displayed, CWnd::RunModalLoop pumps messages by calling AfxGetThread->PumpMessage. If two modal dialog boxes both call the CWinApp object's PumpMessage at the same time, synchronization problems cause the wrong message to get processed on the wrong thread.

<div class="resolution_section">

RESOLUTION
One possible work around is to spawn secondary threads, which in turn display the modal dialog boxes. Each new thread created inside the MFC regular DLL will have a new CWinThread object and a separate message pump.

<div class="status_section">

STATUS
Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.

This problem was corrected in Microsoft Visual C++ .NET.

<div class="moreinformation_section">

MORE INFORMATION
In Visual C++ versions earlier than Visual C++ 4.2, MFC regular DLLs could be accessed only from the same thread that loaded the DLL. Support for external secondary threads was added in Visual C++ 4.2.

The following sample code shows one possible workaround:

UINT ShowMeTheDlg( LPVOID pParam )

{

// Create CWnd object from passed in HWND CFileSecurity FS(CWnd::FromHandle((HWND)pParam)); FS.DoModal; return TRUE; }

void CSubfolderPage::OnBreakit {  // Start MFC Worker thread for modal dialog box. Modal dialog box has // PumpMessage code so, user interface thread is not necessary. // Can't pass CWnds between threads, so pass HWND // After DoModal call above, function returns // and thread terminates. AfxBeginThread(ShowMeTheDlg, (LPVOID)this->GetSafeHwnd); }

<div class="references_section">