If I only post one message to the thread it is fine. But if I post two
messages right after one another the second one is lost and
PostThreadMessage doesn't return an error.
Example.
PostThreadMessage(somemessage); //works
Example2.
PostThreadMessage(somemessage);
PostThreadMessage(somemessage2);
The second message in example2 seems to disappear and PostThreadMessage
doesn't fail. However this causes it to work.
Example3.
Sleep(0);
PostThreadMessage(somemessage);
PostThreadMessage(somemessage2);
I am completely baffled by this and hope I don't have to call Sleep
everytime I want to post messages to my thread. By the way the thread I am
posting to has NO WINDOWS, so I know the messages aren't being intercepted.
Please help :)
while ( !PostThreadMessage( ... ) )
{
Sleep(10);
}
Or use event objects.
"Randy" <z...@somewhere.com> wrote in message
news:u1wYZOGoCHA.948@TK2MSFTNGP10...
The SDK documentation I have mentions using Sleep() or
WaitForSingleObject(), but only to handle the case where the message queue
has not yet been created. Randy's comments imply that the message queue
*does exist* at the time of the second call to PostMessage()... if it
didn't, how would the first message get through? It seems wrong to me that
you have to use Sleep() even when the message queue exists!?
<no...@none.com> wrote in message news:uIQX$aGoCHA.1600@TK2MSFTNGP11...
It seems wrong to me too that's why I hope someone has an idea of what's
going on. Basically I had to put a Sleep(0) before every post message to
make sure it works. Although it probably doesn't hurt my peformance to do
this, it is odd and I still want to know why.
Still hoping someone knows :)
In the processing of the first message, is your application perhaps
running a different message loop such that the second message is
getting pulled and discarded?
For instance, if you display a MessageBox or modal dialog, these have
their own message loops which will not know how to process your
message and will discard it.
Dave
--
MVP VC++ FAQ: http://www.mvps.org/vcfaq
No MessageBoxes or modal dialogs exist when this message is posted. And that
doesn't explain why the Sleep(0) makes it work :(
Can you post the message loop code?
Jay
Sure.
MSG msg; //used to hold the message retrieved from queue
char* buffer; //buffer passed in with message
int* size; //size passed in with message
ZeroMemory(&msg, sizeof(msg));
//Use peek message to force the message queue to be created
//Once it is created set the event showing it has been created
PeekMessage(&msg, NULL, UWM_WRITE_DATA, UWM_WRITE_DATA, PM_NOREMOVE);
SetEvent(thread_event);
//Loop until a WM_QUIT message is received
while(GetMessage(&msg, NULL, 0, 0))
{
if(msg.message == UWM_WRITE_DATA)
{
//if the message is a write message write the buffer to the com
port
//and deallocate the memory
size = (int*)msg.lParam;
buffer = (char*)msg.wParam;
if(*size < SpaceInTransmitBuffer(myport))
PutPacket(myport, *size, buffer);
delete []buffer;
delete size;
ZeroMemory(&msg, sizeof(msg));
}
}
//Loop while there are still messages in the message queue to make sure
//all data is written and deleted
while(PeekMessage(&msg, NULL, UWM_WRITE_DATA, UWM_WRITE_DATA,
PM_REMOVE))
{
if(msg.message == UWM_WRITE_DATA)
{
size = (int*)msg.lParam;
buffer = (char*)msg.wParam;
if(*size < SpaceInTransmitBuffer(myport))
PutPacket(myport, *size, buffer);
delete []buffer;
delete size;
}
}
Just curious: how are you determining whether a message is being received or
not? Are you using TRACE? I've had TRACE's go off into the ether unless a
Sleep is done occassionally.
Just in case...
Jay
Well I'm not using trace I'm not familiar with it, but I've stepped through
the debugger, and also the data with that message is never written out to
the comport, i can monitor it. Also if that message isn't processed I will
get memory leaks and I delete the memory if PostThreadMessage fails but it
doesn't so I get leaks.
Ok. Just a shot. And it definitely sounds like it's dropped (because of the
leaks).
Do you know if it's the first or second message that goes missing?
Jay
This all looks ok (actually, it looks quite nice).
1) Does SpaceInTransmitBuffer or PutPacket use any sort of COM (implied
message loop)?
2) I'm assuming the threads wait for thread_event to be set initially before
posting?
3) If you comment out code (like all the processing code, short of the
delete's) does it then work?
Jay
I'm 100% sure its the second message. For instance this works.
PostThreadMessage(message1); //posted
PostThreadMessage(message2); //not posted
PostThreadMessage(message2); //posted
One more example the second one is not getting posted, otherwise the 3 post
would gripe because its trying to delete memory that is no longer on the
heap.
Makes sense.
I have to ask... :) Initially I saw something like the above and thought you
were just short-handing the parameters for PostThreadMessage. Is that the
case (the PostThreadMessage I know about takes four parameters), as opposed
to a function that only takes one parameter? If it's indeed a function that
only takes 1 param, is that something of yours?
Jay (Grappling in the dark)
Yeah I was just sort of writing psuedo code to just get the message across
:). The actual call would look more like this
PostThreadMessage(writerthreadid, UWM_WRITE_DATA, (WPARAM)buffer,
(LPARAM)size));
Yes they wait on that event to be set thats the whole point :). I may try
commenting that stuff out but it could take a bit to retest :).
--
Tom
"Randy" <z...@somewhere.com> wrote in message
news:uU#bciJoCHA.1868@TK2MSFTNGP12...
I change the part of the loop with the processing to the following code and
now it seems to work!! But I can't comment that out and it still doesn't
explain why it doesn't catch that second message when it isn't commented
out, or why when a Sleep(0) precedes the Posts that it works.
Argh!
if(msg.message == UWM_WRITE_DATA)
{
//if the message is a write message write the buffer to the
comport
//and deallocate the memory
size = (int*)msg.lParam;
buffer = (char*)msg.wParam;
//if(*size < SpaceInTransmitBuffer(myport))
//PutPacket(myport, *size, buffer);
Now comes the fun. :) Selectively comment in the code, process of divide and
conquer, to find the place that is causing the drop. For example, comment in
the line for SpaceInTransmitBuffer(myport) and see if it then fails again.
If it does, go into SpaceInTransmitBuffer and begin disabling code until it
again works; then uncomment code until it fails, dive further in etc. If
not, try the PutPacket call. Eventually, you'll find the code that directly
causes your problem.
Not pretty, but patience will win out.
Jay
Well, here's one:
1) Control when messages can be put posted (via a critical section or
something). Threads must grab the critical section before posting a message.
At the worst, you serialize access to the queue, but Windows is doing that
anyway, so I don't know if you'll have a performance hit.
2) When GetMessage gives you a new message, grab the critical section so the
threads can't post more.
3) Pull all the messages at once out of the queue and put them in a local
array (while PeekMessage(...) blah, blah).
4) Call PutPacket for each message in your local buffer. Since you pulled
all the messages out of the queue, there should be none for PutPacket to
eat; and since you disabled message posting, you also won't have any posted
while PutPacket is happening.
5) Renable posting and loop back to GetMessage.
Another option: don't use the message queue to transport your data. Use a
separate, properly synchronized queue to hold the data. The posted message
would simply be "hey, go look in the queue for data". You still need to
serialize access to the data, but the queue won't need to be locked while
PutPacket is happening. (Or don't use the message queue at all; use a
semaphore. Standard producer/consumer model.)
Jay
Ah, ah...that's a "gotcha". There's no guarantee that the thread posting
the messages won't just acquire the critical section immediately after
releasing it, so it is likely that at some point in the execution, there
will be more than one message posted. You're going to need at least two
synchronization primitives to make this happen.
Thanks for the help!
Of course. And it's not a problem at all. The point of the critical section
is to prevent posting when messages could get lost. It's not to enforce a
single-message protocol. In fact, read the next step:
>
>
> > 3) Pull all the messages at once out of the queue and put them in a
local
> > array (while PeekMessage(...) blah, blah).
This acknowledges that there could be more than one message in the queue.
And in order to prevent them being lost by a message pump in the called
function, they're *all* pulled out and stored locally before any processing
happens.
> > 4) Call PutPacket for each message in your local buffer. Since you
pulled
> > all the messages out of the queue, there should be none for PutPacket to
> > eat; and since you disabled message posting, you also won't have any
> posted
> > while PutPacket is happening.
> > 5) Renable posting and loop back to GetMessage.
> >
Jay
When they say "pass the messages on" they probably mean that their
message loop calls TranslateMessage() and DispatchMesasge(), thus
passing messages on to the designated window.
Your messages, since they are created with PostThreadMessage(), have no
designated window so DispatchMessage() cannot "pass them on."
Norm