Running a CDialog in a separate Thread

Posted on 2001-08-12
Last Modified: 2013-11-20
My app is an SDI. I Have a class that serves as a Singleton and it contains a meethod that should start a thread and display a modeless CDialog derived class within that thread. The reason I do this is so that when the Dialog is displayed, the user can still do something else in the app.

Now, my major prob is that I am getting an ASSERT failure during the CDialog::Create(). I've posted the relevant pieces of code below:

 //   Create Progress Dialog and Display it    
 BOOL ret = m_configProgress.Create();
 if(!ret)   //Create failed.
    AfxMessageBox("Error creating Processing Dialog");



The m_configProgress variable is a member of CFrameWnd class. Any help would be appreciated as I've been on tis for a while now!
Question by:ruff_ryder
  • 3

Author Comment

ID: 6377552
Here's the a copy of the Call Stack:

CWnd::AssertValid() line 884 + 27 bytes
CFrameWnd::AssertValid() line 2123
CMainFrame::AssertValid() line 92
AfxAssertValidObject(const CObject * 0x007b4b98 {CMainFrame}, const char * 0x5f4cd330 THIS_FILE, int 258) line 108
CWnd::CreateDlgIndirect(const DLGTEMPLATE * 0x0042fcf0, CWnd * 0x007b4b98 {CMainFrame hWnd=???}, HINSTANCE__ * 0x00400000) line 260
CDialog::CreateIndirect(const DLGTEMPLATE * 0x0042fcf0, CWnd * 0x007b4b98 {CMainFrame hWnd=???}, void * 0x00000000, HINSTANCE__ * 0x00400000) line 223
CDialog::CreateIndirect(void * 0x0042fcf0, CWnd * 0x00000000 {CWnd hWnd=???}, HINSTANCE__ * 0x00400000) line 200 + 22 bytes
CDialog::Create(const char * 0x0000006b, CWnd * 0x00000000 {CWnd hWnd=???}) line 182 + 20 bytes
CDialog::Create(unsigned int 107, CWnd * 0x00000000 {CWnd hWnd=???}) line 543 + 29 bytes
CXMLToolProgressDlg::Create(CWnd * 0x00000000 {CWnd hWnd=???}) line 73 + 14 bytes
CXMLToolApp::OnConfigurationStart() line 185 + 13 bytes
EvalManager::BeginProcessing(Configuration * 0x007e2378) line 110 + 33 bytes
EvalManager::RunInternal() line 46 + 17 bytes
RunInternalThreadProc(void * 0x007e1f58) line 18 + 13 bytes
_AfxThreadEntry(void * 0x0012f938) line 112 + 13 bytes
_threadstartex(void * 0x007e24c0) line 212 + 13 bytes
KERNEL32! 77e92ca8()

and here's the line of wincore.cpp [Line 884] where the error occurs:

ASSERT((CWnd*)p == this);   // must be us

The "this" variable looks like this in the variable watch window:

this     0x007b4b98 {CMainFrame hWnd=???}

LVL 49

Accepted Solution

DanRollins earned 150 total points
ID: 6378088
The MFC source code in wincore.cpp (directly below the line that asserted) contains this relevant info:

// Note: if either of the above asserts fire and you are
// writing a multithreaded application, it is likely that
// you have passed a C++ object from one thread to another
// and have used that object in a way that was not intended.
// (only simple inline wrapper functions should be used)
// In general, CWnd objects should be passed by HWND from
// one thread to another.  The receiving thread can wrap
// the HWND with a CWnd object by using CWnd::FromHandle.
// It is dangerous to pass C++ objects from one thread to
// another, unless the objects are designed to be used in
// such a manner.

So, you should be able to make it work by using code like this in the thread:

CWnd* pParent= FromHandle( AfxGetMainWnd()->m_hWnd );
BOOL ret= m_configProgress.Create( CMyDlg::IDD, pParent );

But lets back up a bit:
>>The reason I do this is so that when the Dialog is displayed, the user can still do something else in the app

Modeless dialogs are designed to be used that way -- they float above the frame and the user can continue to use the Frame's menus and commands, etc.  What I'm saying, is that it is not usually necessary to spin off a new thread just to display a modeless dialog.

I'm thinking that this dlg box shows the progress of some lengthy operation.  Describe what operation you are doing, and I can give you specific help.  But one common way to do this is this is to drive the dialog's progress control from outside of the dialog.  For instance,

  gpMyModelessDlg->m_cCtlProgress->SetPos( n )

I have used a timer to make calls like this and I have also split off a worker thread to do the work and had it post messages to the dialog and/or progress control.

If your app is stopping during some lengthy operation, a common way to avoid that is to pump messages while doing the lenghty operation:

// start the operation
while( !fDone ) {
   MSG rMsg;
   while ( ::PeekMessage( &rMsg, 0, 0,0, PM_NOREMOVE) ){
   // do some more work, set fDone= TRUE when done

-- Dan

Author Comment

ID: 6382744
Thanx dude! worked nicely!!

Author Comment

ID: 6440883
Dan I'm having another problem now. I split off a worker thread to do some work but I need the main thread to update the Modeless Dialog. I looked on your code:

// start the operation
while( !fDone ) {
  MSG rMsg;
  while ( ::PeekMessage( &rMsg, 0, 0,0, PM_NOREMOVE) ){
  // do some more work, set fDone= TRUE when done

My question is, if im doingthe work in the Worker Thread, how do i access the main thread so that I can call the ::PeekMessage

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Expand LInux Boot partition remotly 3 98
Importing Special Characters in Dynamics GP Through Integration Manager 3 82
while loop over for loop 7 115
format the code in java 6 102
This is to be the first in a series of articles demonstrating the development of a complete windows based application using the MFC classes.  I’ll try to keep each article focused on one (or a couple) of the tasks that one may meet.   Introductio…
Introduction: Displaying information on the statusbar.   Continuing from the third article about sudoku.   Open the project in visual studio. Status bar – let’s display the timestamp there.  We need to get the timestamp from the document s…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.

821 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question