Solved

Running a CDialog in a separate Thread

Posted on 2001-08-12
4
679 Views
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:

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

 m_configProgress.ShowWindow(SW_SHOW);
}

CFrameWndDerived::OnDone()
{
   m_configProgress.ShowWindow(SW_HIDE);
   m_configProgress.DestroyWindow();
}

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!
0
Comment
Question by:ruff_ryder
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
4 Comments
 
LVL 3

Author Comment

by:ruff_ryder
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=???}

0
 
LVL 49

Accepted Solution

by:
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
BOOL fDone= FALSE;
while( !fDone ) {
   MSG rMsg;
   while ( ::PeekMessage( &rMsg, 0, 0,0, PM_NOREMOVE) ){
    AfxGetApp()->PumpMessage();
   }
   // do some more work, set fDone= TRUE when done
}

-- Dan
0
 
LVL 3

Author Comment

by:ruff_ryder
ID: 6382744
Thanx dude! worked nicely!!
0
 
LVL 3

Author Comment

by:ruff_ryder
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
BOOL fDone= FALSE;
while( !fDone ) {
  MSG rMsg;
  while ( ::PeekMessage( &rMsg, 0, 0,0, PM_NOREMOVE) ){
   AfxGetApp()->PumpMessage();
  }
  // 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
0

Featured Post

Enroll in May's Course of the Month

May’s Course of the Month is now available! Experts Exchange’s Premium Members and Team Accounts have access to a complimentary course each month as part of their membership—an extra way to increase training and boost professional development.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Get filename and folder into excel 7 87
countEvens challenge 2 116
Annoying "thing" blocks my view 4 143
Sed question 2 139
Introduction: Finishing the grid – keyboard support for arrow keys to manoeuvre, entering the numbers.  The PreTranslateMessage function is to be used to intercept and respond to keyboard events. Continuing from the fourth article about sudoku. …
Introduction: Ownerdraw of the grid button.  A singleton class implentation and usage. Continuing from the fifth article about sudoku.   Open the project in visual studio. Go to the class view – CGridButton should be visible as a class.  R…
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.
A short tutorial showing how to set up an email signature in Outlook on the Web (previously known as OWA). For free email signatures designs, visit https://www.mail-signatures.com/articles/signature-templates/?sts=6651 If you want to manage em…

738 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