Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

RE: PostThreadMessage and Lost Messages

529 views
Skip to first unread message

RobKinney1

unread,
Oct 4, 2007, 4:00:01 PM10/4/07
to
I should probably mention that my signature in the .h file for the called
function is:
LRESULT OnNewTest(WPARAM wParam, LPARAM lParam);

And that the entry in the MessageMap is:
ON_MESSAGE(UWM_TEST, OnNewTest)

And the definition of UWM_TEST is:
#define UWM_TEST (WM_USER + 1)

(although I read on Joe's site it should be WM_APP + __ ) -- just wanted to
keep this as close to the stuff already programed though.

Anything wrong in these areas that would be causing the behavior?

Thanks again,

Rob

Michael K. O'Neill

unread,
Oct 4, 2007, 4:09:15 PM10/4/07
to

"RobKinney1" <mydigital...@gmail.com.NOSPAMPLEASE> wrote in message
news:111FADAD-8524-4399...@microsoft.com...
> Using VC++ 6.0:
>
> Hello programmers!
>
> Question - I have been battling this for 2 days now:
> Why are some of my messages ignored or lost when I do a
PostThreadMessage()
> from a worker thread to my CWinApp derived class?
>

This is known and documented behavior for PostThreadMessage, which should
never be used to post a message to a thread if the thread has any visible UI
components. See the MSDN documentation for PostThreadMessage, at
http://msdn2.microsoft.com/en-us/library/ms644946.aspx , which contains the
following text:

"Messages sent by PostThreadMessage are not associated with a window. As a
general rule, messages that are not associated with a window cannot be
dispatched by the DispatchMessage function. Therefore, if the recipient
thread is in a modal loop (as used by MessageBox or DialogBox), the messages
will be lost. To intercept thread messages while in a modal loop, use a
thread-specific hook."

Your thread will also be in a modal loop if the user is doing something very
simple, like dragging the application's window around on the desktop, or
re-sizing it. Try dragging/resizing your simple MDI example program, and
see if messages are lost.

See also explanations that abound on the web, and are similar to this one:
"Don't Use the Win32 API PostThreadMessage() to Post Messages to UI Threads"
at http://www.devx.com/tips/Tip/14720


RobKinney1

unread,
Oct 4, 2007, 3:51:02 PM10/4/07
to
Using VC++ 6.0:

Hello programmers!

Question - I have been battling this for 2 days now:
Why are some of my messages ignored or lost when I do a PostThreadMessage()
from a worker thread to my CWinApp derived class?

(I just made a simple MDI application from the new application wizard and am
trying to post messages to the CWinApp class that is generates)

My behavior explained:
The simple sample app I made works fine. I can execute the following line
of code from a worker thread:
AfxGetApp()->PostThreadMessage ( UWM_TEST, 5, 0 );

... And catch it in my CWinApp like this:
LRESULT CTestMessagePassingApp::OnNewTest(WPARAM wParam, LPARAM lParam)
{
...
}

It never fails. However, when I go to my larger project and implement
this, it works about 98% of the time. But sometimes my worker thread will
post the message and the CWinApp class never receives it! (or chooses to
discard it).

I have read article http://support.microsoft.com/kb/142415 and have tried
overriding PreTranslateMessage but that is still causing the same behavior
before I overrode it -- the CWinApp still sometimes misses this message.

I read Joe's article about safe message passing (good article):
http://www.flounder.com/iocompletion.htm
But cannot figure out how that works to pass messages directly to the
CWinApp thread (any suggestions if you are out there Joe?).

The app I am working on is huge and so heavily implemented at the CWinApp
level (instead at the MainFrm or other child window level) that I kinda have
to stay in the realm of getting messages to the CWinApp derived class.

Any suggestions?

Thanks,

Rob

David Lowndes

unread,
Oct 4, 2007, 4:14:27 PM10/4/07
to
>Why are some of my messages ignored or lost when I do a PostThreadMessage()
>from a worker thread to my CWinApp derived class?

Rob,

PostThreadMessage posts a message to a thread with no specific window.
To get the message to your handler it relies on your application's
message loop getting called. In some circumstances (such as when
operating a menu, displaying a message box or true modal dialog box)
your application's message loop is bypassed for generic ones inside
Windows. This message loop doesn't know what to do with your message,
so it gets discarded.

The best solution to this situation is to use PostMessage to post the
message to a specific window.

Dave

Scott McPhillips [MVP]

unread,
Oct 4, 2007, 4:43:20 PM10/4/07
to
"RobKinney1" <mydigital...@gmail.com.NOSPAMPLEASE> wrote in message
news:76A6EF97-EE6A-47DC...@microsoft.com...
> Thank you for posting Michael. This is starting to make sense. So on
> that
> tip they give about using PostMessage instead and post to a window, are
> they
> inferring you post to CMainFrame? Or do I have to make some kind of
> hidden
> window to post to that handles these messages?
>
> If so, and I have to post to a different window, how does that message
> intercepting window going to post back to the GUI CWinApp class and have
> it
> invoke/call a function?
>
> Maybe I am missing something real simple to this concept....
>
> Thanks,
>
> Rob

You can PostMessage to any window created in the main thread. CMainFrame is
a good choice but any window will work.

The message handler in the window can simply use AfxGetApp() to get a
pointer to the CWinApp. That pointer can be used to call an app function.

--
Scott McPhillips [VC++ MVP]

RobKinney1

unread,
Oct 4, 2007, 4:30:01 PM10/4/07
to

Thank you for posting Michael. This is starting to make sense. So on that

RobKinney1

unread,
Oct 4, 2007, 4:33:01 PM10/4/07
to

"David Lowndes" wrote:

Dave, Thank you for your reply! Can you help me with the last comment in
your post about using PostMessage to another window? As I was replying to
Michael above, I was asking how this is done and how that window I would be
posting to would know how to in turn call or invoke a function back in the
CWinApp class.

I think I am seeing a design flaw where not much should be implemented in
the CWinApp derived class, but at a different level like in the CMainFrame
class...

Thanks!

Rob

RobKinney1

unread,
Oct 4, 2007, 5:19:01 PM10/4/07
to

"Scott McPhillips [MVP]" wrote:

Hello Scott. Thank you for replying!

So you are saying that I execute a PostMessage() in a worker thread. Then I
catch that message in CMainFrame. Then from CMainFrame I use AfxGetApp() to
execute something back in the CWinApp based class?

I guess that makes sense. So then I would assume that you can call
AfxGetApp()->MyFunctionInTheCWinApp().... but when I use AfxGetApp()->, the
function is not listed -- just the functions listed in the base class
CWinApp. Is there a way to get at my custom functions in that level from
CMainFramer?

Maybe I am not supposed to have any new functions in my CWinApp based class
that are accessible from the outside, but rather just internal helper
functions?

I think I am missing the boat somewhere here.

Thank you very much for your help!

Rob

David Lowndes

unread,
Oct 4, 2007, 5:32:25 PM10/4/07
to
>Dave, Thank you for your reply! Can you help me with the last comment in
>your post about using PostMessage to another window? As I was replying to
>Michael above, I was asking how this is done and how that window I would be
>posting to would know how to in turn call or invoke a function back in the
>CWinApp class.

Rob,

You'd probably find it easiest to post the message to your
application's top level main frame window, and then from there you
could (if you really needed to) call AfxGetApp to gain access to your
application object and call a public method of that class.

>I think I am seeing a design flaw where not much should be implemented in
>the CWinApp derived class, but at a different level like in the CMainFrame
>class...

In this situation (where you need the window, it may be optimal to
have that functionality in the main frame window rather than the
application.

Dave

RobKinney1

unread,
Oct 4, 2007, 5:41:00 PM10/4/07
to

"David Lowndes" wrote:

Sounds good. I am not sure why AfxGetApp()-> is not pulling up my custom
functions back in the CWinApp class, but I don't see why we couldn't just
migrate everything from the CWinApp class up to the CMainFrame class as you
suggest.

If I did somehow figure out the first way (getting AfxGetApp()-> to pull up
my and list my custom functions), is that an ok/safe way of calling them?
-- cause then minimal change would be needed -- I would just be using
CMainFrame to route my messages.

Thanks again for replying!

Rob

David Lowndes

unread,
Oct 4, 2007, 6:31:41 PM10/4/07
to
>Sounds good. I am not sure why AfxGetApp()-> is not pulling up my custom
>functions back in the CWinApp class

You'll need to cast it to your specific derived application class.

>If I did somehow figure out the first way (getting AfxGetApp()-> to pull up
>my and list my custom functions), is that an ok/safe way of calling them?

It should be.

Dave

Scott McPhillips [MVP]

unread,
Oct 4, 2007, 6:51:58 PM10/4/07
to
"RobKinney1" <mydigital...@gmail.com.NOSPAMPLEASE> wrote in message
news:EC68CBE9-4403-435E...@microsoft.com...

> Sounds good. I am not sure why AfxGetApp()-> is not pulling up my custom
> functions back in the CWinApp class, but I don't see why we couldn't just
> migrate everything from the CWinApp class up to the CMainFrame class as
> you
> suggest.
>
> If I did somehow figure out the first way (getting AfxGetApp()-> to pull
> up
> my and list my custom functions), is that an ok/safe way of calling them?
> -- cause then minimal change would be needed -- I would just be using
> CMainFrame to route my messages.
>
> Thanks again for replying!
>
> Rob

AfxGetApp() returns a CWinApp pointer. To call your added functions you can
cast it to your own app class.

CYourApp* p = (CYourApp*)AfxGetApp();
p->YourAppFunction();

But this is ugly and not really recommended. The more elegant way is to add
an extern declaration in yourapp.h

extern CYourApp theApp;

Then to call your functions you can simply do:

theApp.YourAppFunction();

Norman Diamond

unread,
Oct 4, 2007, 10:47:38 PM10/4/07
to
"RobKinney1" <mydigital...@gmail.com.NOSPAMPLEASE> wrote in message
news:81AAD006-86B5-4F95...@microsoft.com...

> "Scott McPhillips [MVP]" wrote:
>>
>> You can PostMessage to any window created in the main thread. CMainFrame
>> is a good choice but any window will work.
>>
>> The message handler in the window can simply use AfxGetApp() to get a
>> pointer to the CWinApp. That pointer can be used to call an app
>> function.
>
> So you are saying that I execute a PostMessage() in a worker thread. Then
> I catch that message in CMainFrame. Then from CMainFrame I use
> AfxGetApp() to execute something back in the CWinApp based class?
>
> I guess that makes sense. So then I would assume that you can call
> AfxGetApp()->MyFunctionInTheCWinApp().... but when I use AfxGetApp()->,
> the function is not listed

For this you need to remember a bit about the C++ language itself, besides
Microsoft's frameworks. AfxGetApp() returns a pointer of a type that
Microsoft knew about. You know the type of your actual application's class,
which is derived from Microsoft's base class. So cast this pointer to your
type. Then you can call your method.

Ian Semmel

unread,
Oct 5, 2007, 3:45:14 PM10/5/07
to
I got around this problem by embedding a window into each CWinThread ala
CAsyncSocket message pump.

I supply a property in the thread which returns the CWnd and clients post
using this.

I reckon that this is a bug in MFC, but some call it a feature.

Joseph M. Newcomer

unread,
Oct 6, 2007, 9:05:14 PM10/6/07
to
Because you cannot PostThreadMessage to any class in the main GUI thread. It doesn't
work. Read the documentation for PostThreadMessage. It explains why it won't work.

It is erroneous to do so. Don't do it.
joe

On Thu, 4 Oct 2007 12:51:02 -0700, RobKinney1 <mydigital...@gmail.com.NOSPAMPLEASE>
wrote:

Joseph M. Newcomer [MVP]
email: newc...@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm

Joseph M. Newcomer

unread,
Oct 6, 2007, 9:06:34 PM10/6/07
to
Except that it is questionable why you would ever need to access the app class from any
other class.
joe

On Thu, 4 Oct 2007 16:43:20 -0400, "Scott McPhillips [MVP]" <org-dot-mvps-at-scottmcp>
wrote:

Joseph M. Newcomer

unread,
Oct 6, 2007, 9:08:02 PM10/6/07
to
That's correct. That's because you get a CWinApp*, which would not have any of your
methods. You would need to write
((CMyApp *)AfxGetApp())->MyMethod(...);
which should raise a massive big red flag that you are doing something that violates good
modular design.
joe

On Thu, 4 Oct 2007 14:19:01 -0700, RobKinney1 <mydigital...@gmail.com.NOSPAMPLEASE>
wrote:

Joseph M. Newcomer

unread,
Oct 7, 2007, 2:39:11 PM10/7/07
to
See below...
On Thu, 4 Oct 2007 14:41:00 -0700, RobKinney1 <mydigital...@gmail.com.NOSPAMPLEASE>
wrote:

>
>
>"David Lowndes" wrote:
>
>> >Dave, Thank you for your reply! Can you help me with the last comment in
>> >your post about using PostMessage to another window? As I was replying to
>> >Michael above, I was asking how this is done and how that window I would be
>> >posting to would know how to in turn call or invoke a function back in the
>> >CWinApp class.
>>
>> Rob,
>>
>> You'd probably find it easiest to post the message to your
>> application's top level main frame window, and then from there you
>> could (if you really needed to) call AfxGetApp to gain access to your
>> application object and call a public method of that class.
>>
>> >I think I am seeing a design flaw where not much should be implemented in
>> >the CWinApp derived class, but at a different level like in the CMainFrame
>> >class...
>>
>> In this situation (where you need the window, it may be optimal to
>> have that functionality in the main frame window rather than the
>> application.
>>
>> Dave
>>
>
>Sounds good. I am not sure why AfxGetApp()-> is not pulling up my custom
>functions back in the CWinApp class,

****
Because it is not supposed to! AfxGetApp is specified as returning a CWinApp*, which it
does. Your functions are not part of the class CWinApp*. This is an elementary C++
language issue.
****


>but I don't see why we couldn't just
>migrate everything from the CWinApp class up to the CMainFrame class as you
>suggest.

****
I make it a policy to NEVER use my CWinApp-derived class outside its implementation file.
Since I have not found a reason to use it in years, I question why anyone (particularly
Microsoft) thinks it is necessary (the first thing I do with code these days is rip out
every #include "whatever.h" for whatever.h being my CWinApp-derived class definition.
Either the #include disappears entirely, or it is replaced by #include "resource.h" which
is all that is needed. There is no need to use the CWinApp class outside the CWinApp
implementration. It's called "modular design". I also don't use the CMainFrame class
outside the CMainFrame, and the CMainFrame class NEVER needs to know about any view
windows that are under it, or documents. I don't even use GetActiveView or
GetActiveDocument if I need a method from my classes; if I can't do it with the CView or
CDocument class methods, it doesn't belong.
*****


>
>If I did somehow figure out the first way (getting AfxGetApp()-> to pull up
>my and list my custom functions), is that an ok/safe way of calling them?
>-- cause then minimal change would be needed -- I would just be using
>CMainFrame to route my messages.

****
Again, this is basic C++ language knowledge, but you shouldn't be doing it. I gave you
the answer earlier, and it is always a sure sign that there is a design problem.
joe
****


>
>Thanks again for replying!
>
>Rob

RobKinney1

unread,
Oct 8, 2007, 12:13:02 PM10/8/07
to

"Scott McPhillips [MVP]" wrote:

> AfxGetApp() returns a CWinApp pointer. To call your added functions you can
> cast it to your own app class.
>
> CYourApp* p = (CYourApp*)AfxGetApp();
> p->YourAppFunction();
>
> But this is ugly and not really recommended. The more elegant way is to add
> an extern declaration in yourapp.h
>
> extern CYourApp theApp;
>
> Then to call your functions you can simply do:
>
> theApp.YourAppFunction();
>
> --
> Scott McPhillips [VC++ MVP]

Thanks Scott! This worked great. I am now using this method instead of the
PostThreadMessage!

Rob

RobKinney1

unread,
Oct 8, 2007, 12:16:00 PM10/8/07
to

"Joseph M. Newcomer" wrote:

> Because you cannot PostThreadMessage to any class in the main GUI thread. It doesn't
> work. Read the documentation for PostThreadMessage. It explains why it won't work.
>
> It is erroneous to do so. Don't do it.
> joe

Thank you Joe for your commenting throughout this thread. :~]

Yes, I think this could use a redesign sometime to help fix all these
issues. I wasn't aware of a lot of these until you pointed them out.

This will be a good reference thread for me later!

Thanks,

Rob

0 new messages