Click to See Complete Forum and Search --> : PostThreadMessage not received in time
DumbMonkey
September 12th, 2005, 09:40 AM
Hi all,
I wonder if anyone could give me some suggestions on this problem.
I have a thread running in a class with a GetMessage(....) function.
In another class I am posting messages to the thread with
PostThreadMessage(ThreadID, WM_SOMETHING, MessageLength, (LONG) Message);
The problem I have is that the messages are not processed in time in the GetMessage thread, as the Message data is being copied over when new calls come into the PostThreadMessage function. Therefore GetMessage processes the new data and the old data is lost.
Can anyone suggest a way to guarantee every message is processed?
Much appreciated.
cvogt61457
September 12th, 2005, 09:55 AM
What do you mean by "in time"?
What message are you sending?
What is "copied over"?
DumbMonkey
September 12th, 2005, 10:03 AM
I mean in time, as in the PostThreadMessage function is being called before the GetMessage thread has received the message.
I send about 10/20 byte messages each time using the function-
VOID SendMessage(LONG *Data, LONG DataLength)
{
PostThreadMessage(ThreadID, WM_MYMESSAGE, DataLength, (LONG) Data));
}
Whats happening is SendMessage is repeatedly being called and posting messages, but the Data is getting written over before the GetMessage thread has processed it. Hence i lose messages.
Thanks.
cvogt61457
September 12th, 2005, 10:23 AM
Try using WM_COPYDATA if you want to send more that a couple of bytes
of data.
With WM_COPYDATA, you can send all the data in a single data block.
Note: The data block must contain only POD (Plain Old Data)
No pointers, no C++ classes.
Go to www.msdn.microsoft.com and search for WM_COPYDATA.
wildfrog
September 12th, 2005, 10:34 AM
Try using WM_COPYDATA if you want to send more that a couple of bytes of data.You cannot use WM_COPYDATA with PostThreadMessage. WM_COPYDATA is for synchronous use only.
- petter
DumbMonkey
September 12th, 2005, 10:40 AM
Many thanks,
Have been trying that, but it seems that PostThreadMessage cannot deal with WM_COPYDATA message, it only seems that WM_COPYDATA can be used with SendMessage and not PostMessage, according to the documentation.
Cheers.
wildfrog
September 12th, 2005, 10:53 AM
The problem I have is that the messages are not processed in time in the GetMessage thread, as the Message data is being copied over when new calls come into the PostThreadMessage function. Therefore GetMessage processes the new data and the old data is lost.
Why not make a copy of the data, and use PostThreadMessage to send the pointer to the copy. Then, after the message is handled, delete the copy.
- petter
cvogt61457
September 12th, 2005, 10:58 AM
OK, need a plan B.
It seems that the sender and receiver are both in your program. (??)
Create a separate, thread-safe data queue to hold the data. For each data block placed in the queue, send your message to the receiver. The
receiver can then pull the data from the queue on each message.
The queue must be thread-safe.
MikeAThon
September 12th, 2005, 03:42 PM
On the sender side, allocate new memory for each new message; on the receiver side delete it. For example:
// .. sender side
MyMessage* pMess = new MyMessage;
pMess->populate fields
PostThreadMessage( ThreadID, WM_SOMETHING, sizeof( MyMessage), (LPARAM) pMess );
// .. receiver side
MyMessage* pMess = (MyMessage*)(lParam);
pMess->use the message
delete pMess;
This way, you are not trying to re-use the same block of memory for all of your messages. Rather, a new block of memory is used uniquely for each different message. It therefore does not matter if your posted messages are not retrieved/processed "in time".
Note: It's possible to lose messages posted by PostThreadMessage, under some very ordinary circumstances, if the target thread is a UI thread. Most notably, you will definitely lose messages if the UI thread is in a modal loop, like when a modal dialog is being displayed or when the user is dragging the window around the screen. See "PostThreadMessage Messages Lost When Posted to UI Thread" at http://support.microsoft.com/default.aspx?scid=kb;en-us;183116. Note that, according to Microsoft, "This behavior is by design".
If you are posting to a UI thread, then it's probably better if you don't use PostTHreadMessage.
Mike
DumbMonkey
September 13th, 2005, 04:17 AM
Many thanks to you all.
Mike, I discovered something like your solution on the web. I am passing long arrays between threads so could i do something like this-
VOID Send(LONG *Message, LONG MessageLength)
{
LONG *Data = new LONG[MessageLength];
memcpy(Data, Message, MessageLength*4);
PostThreadMessage(ThreadID, WM_WHATEVER, MessageLength, (LPARAM) Data);
}
...Receiver side
LONG *Data = (LONG *) Msg.lparam;
... use data
delete Data;
Is this acceptable? Was wondering if the delete function would know how much memory to free if its across threads?
Much appreciated and many thanks to you all,
DumbMonkey.
wildfrog
September 13th, 2005, 05:14 AM
Is this acceptable?
Well almost, but your delete should look like this:
delete[] Data;
But you should re-read what MikeAThon said about "It's possible to lose messages...", because if you loose one or multiple of the messages you'll end up with a memory leak (and then you might want to consider a queue-like mechanism mentioned by cvogt61457).
- petter
cvogt61457
September 13th, 2005, 10:09 AM
Is the receiver thread a UI thread?
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.