DestroyWindow () in a seperat thread.

I am trying to destroy a dialog in a thread. The dialog is created in the main thread and then I start a new thread and in that thread I want to use DestroyWindow (). GPF every time I try to destroy it. This is the code used:

void CMyView::ScanDirectory (LPCTSTR lpszDirectory)
{
if (!this->IsWindowVisible ())
     return;
m_dlgProgress.Create (IDD_PROGRESS_DIALOG, this);

//Start the thread
AfxBeginThread (ScanThread, this);
}

UINT ScanThread( LPVOID pParam )
{
CMyView* pView = (CMyView*)pParam;

  //Do my stuff
pView->m_dlgProgress.DestroyWindow ();
}

Last line kills the program, why can't I do it like this? The DestroyWindow function is called but when CDialog::DestroyWindow is called, kaboom. Is there any other way to destroy the dialog? How can I fix this?
LVL 1
joakimfAsked:
Who is Participating?

[Webinar] Streamline your web hosting managementRegister Today

x
 
Vinayak KumbarConnect With a Mentor Sr Program ManagerCommented:
HI,

modify the code like
void CMyView::ScanDirectory (LPCTSTR lpszDirectory)
                     {
                     if (!this->IsWindowVisible ())
                          return;
                     m_dlgProgress.Create (IDD_PROGRESS_DIALOG, this);

                     //Start the thread
                     AfxBeginThread (ScanThread, this);
                     }

                     UINT ScanThread( LPVOID pParam )
                     {
                     CMyView* pView = (CMyView*)pParam;

                       //Do my stuff
                     pView->m_dlgProgress.EndDialog (0);
                     }

Or
u can map the OnOK() for that dialog class, then make that function declaration as public in .h file and then use
pView->m_dlgProgress.OnOK();//similarly OnCancel()

But the best way I suggest is to make use of pointer. U have declared as
CDialog m_dlgProgress; instead of that declare as
CDialog *m_dlgProgress;
then in the constructor do
m_dlgProgress = NULL;
then the thread code will be

void CMyView::ScanDirectory (LPCTSTR lpszDirectory)
                     {
                     if (!this->IsWindowVisible ())
                          return;
                     m_dlgProgress = new CDialog;//Or Ur dialog class name
                     m_dlgProgress->Create (IDD_PROGRESS_DIALOG, this);
                     m_dlgProgress->ShowWindow(SW_SHOW);
                     //Start the thread
                     AfxBeginThread (ScanThread, this);
                     }

                     UINT ScanThread( LPVOID pParam )
                     {
                     CMyView* pView = (CMyView*)pParam;

                       //Do my stuff
                     if(pView->m_dlgProgress)
                    {
                              delete pView->m_dlgProgress;
                              pView->m_dlgProgress = NULL;
                    }
                   
                     }
Thats it.

Try it out.
VinExpert
0
 
vachoohoCommented:
pView->m_dlgProgress.PostMessage(WM_CLOSE);

instead of
pView->m_dlgProgress.DestroyWindow ();


0
 
joakimfAuthor Commented:
I tried to use the PostMessage method and the dialog doesn't close. On the other hand the program doesn't krash either, any other ideas?
0
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.

 
vachoohoCommented:
pView->m_dlgProgress.PostMessage(WM_COMMAND, ID_CANCEL);
0
 
joakimfAuthor Commented:
I tried to use the PostMessage method and the dialog doesn't close. On the other hand the program doesn't krash either, any other ideas?
0
 
vachoohoCommented:
pView->m_dlgProgress.PostMessage(WM_COMMAND, ID_CANCEL);
0
 
vachoohoCommented:
You can try to create dialog in the tread


UINT ScanThread( LPVOID pParam )
{
CMyView* pView = (CMyView*)pParam;
m_dlgProgress.Create (IDD_PROGRESS_DIALOG, this);

  //Do my stuff
pView->m_dlgProgress.CloseWindow ();
pView->m_dlgProgress.DestroyWindow ();
}

this could help
0
 
joakimfAuthor Commented:
Yes I tried that and it works fine, the problem is that I want to be able to cancel the operation by pressing the cancel button. By creating the dialog in the same thread I destory it, the cancel button doesn't work.
0
 
joakimfAuthor Commented:
The pointer thing didn't work, so I had to use the following:

if (m_dlgProgress.m_hWnd != NULL)
      m_dlgProgress.DestroyWindow ();
m_dlgProgress.Create (IDD_PROGRESS_DIALOG, this);


And then in the thread:
pView->m_dlgProgress.EndDialog (0);

Thanks for your help....
0
 
vachoohoCommented:
The problem is that when you press Cancel button dialog is closed and when thread is finished you try to destroy already destroyed dialog. This is the source of GPF you receive.


You can do the following:
add member variable in you dialog class
HANDLE m_hThread;

in dialog constructor you use add
m_hThread = NULL;

//Start the thread and store handle in dialog
m_dlgProgress.m_hThread =
AfxBeginThread(ScanThread, this)->m_hThread;

overwrite dialog's ONCancel() function
add the following before calling default CDialog::OnCalcel() method

TerminateThread(m_hThread, 1);

this will stop the thread and close your progress dialog.

But this is not the best way
because your thread stack will not be freed.



You can try the following code before DestroyWindow()

if(::IsWindow(pView->m_dlgProgress.m_hWnd))
pView->m_dlgProgress.DestroyWindow ();

this will not cause GPF in code but your cancel button will not actualy cancel scan operation - it will only close progress dialog.

0
All Courses

From novice to tech pro — start learning today.