Link to home
Start Free TrialLog in
Avatar of toannds
toannds

asked on

A very simple multi-thread program but couldn't work

Hello,

I'm a beginner to MFC. I wanna practise multi-thread programming so I create a class deriving from CDialog. Its task is simple: it displays the clock in a static text control.

I cannot understand why I keep receiving the "Debug Assertion Failed!" at the line UpdateData(FALSE) of the my UpdateClock() member function. This error occured in the debug version only; the release version worked normally. By tracing I saw the pointer that I catch the ThreadFunc (it is pDlg) and the pParam in AfxBeginThread() are the same. Then where is my mistake?

I tried other way: Pass the window handle of the dialog m_hWnd the ThreadFunc() instead and using the CWnd::FromHandle(HWND hWnd) to get the pointer to my dialog object but this leads to an unhandled exception.

Can you show me the mistake that I made.
Thanks.

Song Toan
toannds@hotmail.com

----------------
Here is my code:


class CMultiThreadDlg : public CDialog
{
public:
      // Dialog Data
      //{{AFX_DATA(CMultiThreadDlg)
      enum { IDD = IDD_MULTITHREAD_DIALOG };
      CString      m_strTime;      // static text control
      //}}AFX_DATA
      // ... other members ...
protected:
      BOOL bContinue;
      void UpdateClock();
      static UINT ThreadFunc(LPVOID pParam);
      // ... other members ...
};


BOOL CMultiThreadDlg::OnInitDialog()
{
      CDialog::OnInitDialog();

      bContinue = 1;            // this flag is used to stop the thread later
      pThread = AfxBeginThread(
                  ThreadFunc,
                  (LPVOID) this);      // pass the pointer as parameter to ThreadFunc()
      return TRUE;
}

void CMultiThreadDlg::UpdateClock()
{
      CTime t;
      
      t = CTime::GetCurrentTime();
      m_strTime = t.Format("%H:%M:%S");
      UpdateData(FALSE);      // Debug Assertion Failed here!
}

UINT CMultiThreadDlg::ThreadFunc( LPVOID pParam )      // this is a static member function
{
      CMultiThreadDlg *pDlg = (CMultiThreadDlg *)pParam;
      
      while ( pDlg->bContinue ) pDlg->UpdateClock();
      return 0;
}

BOOL CMultiThreadDlg::DestroyWindow()
{
      bContinue = 0;            // terminate the thread      
      return CDialog::DestroyWindow();
}
ASKER CERTIFIED SOLUTION
Avatar of jhance
jhance

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of toannds
toannds

ASKER

Hi jhance,

Thank you for your quick answer. May I ask you some more?

1-It's not clear to me that weather I should not use CWnd pointer or I should not use any other class in the that manner (using pointer to a object in ThreadFunction)?

2-Also I want to know how can I get a pointer to my CMultiThreadDlg from the dialog handle that I pass it to the ThreadFunc()? (the CWnd::FromHandle returns the pointer to CWnd only)

Thanks.
1) You should not save and use a CWnd pointer at a later time.  You should not use a CWnd pointer as a argument passed to the thread function.  Where you have:

pThread = AfxBeginThread(ThreadFunc,
                (LPVOID) this); // pass the pointer as parameter to ThreadFunc()
                return TRUE;
                }

do this instead:

pThread = AfxBeginThread(
                ThreadFunc,
                (LPVOID) this->m_hWnd);
                return TRUE;
                }


2) To have your thread function notify your main window that something has happened, do this:

::PostMessage(hWnd, WM_USER+1, (WPARAM)wParam, (LPARAM)lParam);

Where wParam and lParam are data values you want sent back to the main window.
Avatar of toannds

ASKER

And can I use SendMessage() instead of PostMessage()?
Avatar of toannds

ASKER

jhance,

I give you 50 points instead of 10.
Please read the 10109694 question:

https://www.experts-exchange.com/jsp/qShow.jsp?ta=cprog&qid=10109694 

Thanks.