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

Use Case: Protecting a Hybrid Cloud Infrastructure

Microsoft Azure is rapidly becoming the norm in dynamic IT environments. This document describes the challenges that organizations face when protecting data in a hybrid cloud IT environment and presents a use case to demonstrate how Acronis Backup protects all data.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Whole sheet autoscrub still needed 19 50
Prevent this page from creating additional dialogs. 3 532
matchUp  challenge 6 64
wordmultiple challenge 12 133
Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
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.
In a recent question ( here at Experts Exchange, a member asked how to add page numbers to a PDF file using Adobe Acrobat XI Pro. This short video Micro Tutorial sh…

809 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