Click to See Complete Forum and Search --> : SendMessage from Thread


DHunter21
August 30th, 1999, 12:51 PM
Hi there,

I've created a thread to monitor my comport. When something is sent to the comport, I read the data, put it it a different buffer, and then tell the parent Dialog that theres data waiting. In my thread proc I use :

pseudoThis->m_pParentDlg->PostMessage(WM_COMPORT, pComInfo->nPort, 0);

To process this I use:

void CMyMainDlg::OnMsgSendCommand(LPARAM lParam)
{
...
}

No when I use this in Release Mode, the entire program crashes. However everything is fine in Debug.

Does anyone see a problem here?

Is there a better way to tell the parent that there's something waiting?

Thanks

Dustin

August 30th, 1999, 03:02 PM
Hi,

I'd be wary of the pseudoThis pointer. Most books that I've read recommend that you pass a HWND of the "parent" window when you create your thread, instead of a CWnd* pointer. All you have to do is use ::PostMessage and cast the data param as HWND to post the message.


Also, you should declare your message handler like this:

afx_msg LRESULT MyMessageHandler(WPARAM wParam, LPARAM lParam);

put this in your .cpp message map:
ON_COMMAND(WM_MYMESSAGE, MyMessageHandler)

and define it like this:

LRESULT CMyClass::MyMessageHandler(WPARAM wParam, LPARAM lParam)
{

return 1;
}

Small point though....

HTH,

Harvey Hawes
h.hawes@home.com

Rail Jon Rogut
August 30th, 1999, 03:51 PM
Hi Dustin

This was discussed in Paul DiLascia's C++ Q&A column in Microsoft Systems Journel in July 1999.

"In the March 1999 issue, a reader asked about a mysterious bug he was experiencing in release builds only. The problem had to do with ON_MESSAGE which lets you handle an arbitrary message such as WM_MYMESSAGE.

const WM_FOO = WM_USER + 1;
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_MESSAGE(WM_FOO, OnFoo)
END_MESSAGE_MAP

The handler function OnFoo must have the signature

LRESULT OnFoo(WPARAM, LPARAM)


That is, it should take a WPARAM and LPARAM, and return an LRESULT. If instead OnFoo has no arguments and returns void (an easy error if you don't use the arguments), your code will compile and even run - in debug builds. But because of the differences in stack checking and correction, it fails in release builds - in an especially gruesome and hard-to-understand way. (The stack becomes corrupt, the program goes on executing a while, then crashes somewhere else far removed from the real bug.)"

He then goes on to explain a method of protecting yourself from this.

Rail

------------
Recording Engineer/Software Developer
Rail Jon Rogut Software
http://home.earthlink.net/~railro/
railro@earthlink.net

chafey
August 30th, 1999, 03:55 PM
You must declare your function with the exact parameters that will be passed to it. MFC's message handling macros cannot enforce type and therefore allow you to mismatch functions which result in crashes as you are describing. Harvery's declarations are the correct one. His point about using ::PostMessage() is important as well, but since it works in debug mode without asserting, you are probably doing this properly already.

Chris Hafey

DHunter21
August 30th, 1999, 05:14 PM
Ok, when i followed what was said, I don't get the errors, but the message doesn't get processed either. One thing i noticed is that in my orignal code I had:

ON_MESSAGE(WM_COMPORT, OnComPort)

And then i noticed that you guys used ON_COMMAND instead of ON_MESSAGE. I changed that, and the problem went away. However, the message function never got called either. Whats the difference here? Which should I use.

The rest is defined like:

afx_msg LRESULT OnComPort(WPARAM wParam, LPARAM lParam);

LRESULT CCodecGUI2Dlg::OnComPort(WPARAM wParam, LPARAM lParam)
{
....
return 1;
}

I then call it like:

pseudoThis->m_pParentDlg->PostMessage(WM_COMPORT, 0, pComInfo->nPort);

I was going to change this to ::PostMessage() but I couldn't understand what was meant by casting the data param as HWND to post the message? What would this look like? I would think that the HWND required should be that of the parent dialogs. And wouldn't I get that from GetSafeHwnd() ?

Thanks

Dustin

Rail Jon Rogut
August 30th, 1999, 06:29 PM
Hi Dustin

In your CCodecGUI2Dlg class' cpp file, add:

BEGIN_MESSAGE_MAP(CCodecGUI2Dlg, CDialog)
//{{AFX_MSG_MAP(CCodecGUI2Dlg)
:
:
//}}AFX_MSG_MAP
ON_MESSAGE(WM_COMPORT, OnComPort)
END_MESSAGE_MAP()

Now, add a new funtion to your CCodecGUI2Dlg class:

LRESULT CCodecGUI2Dlg::OnComPort(WPARAM wParam, LPARAM lParam)
{
// Do whatever you want to do

return 0L; // Place a break point here to test
}

In the CCodecGUI2Dlg's header file, add a public function declaration:

LRESULT OnComPort(WPARAM wParam, LPARAM lParam);

Also in the header file add:

#ifndef WM_COMPORT
#define WM_COMPORT (WM_USER+2000)
#endif

Now finally, in your thread, you can call:

pseudoThis->m_pParentDlg->PostMessage(WM_COMPORT, 0, pComInfo->nPort);



and it will reach your function and work as you desire.

Rail


------------
Recording Engineer/Software Developer
Rail Jon Rogut Software
http://home.earthlink.net/~railro/
railro@earthlink.net

Crator
August 31st, 2000, 04:57 PM
You helped me solve a bug I have been working on for days!

Thank you so much for posting this message!

Phil