-
June 27th, 2014, 12:44 PM
#1
PostMessage
I found a very strange behaviour.
Im sending a message from a worker thread to the main window.
If I uncomment the 'cout' line its working properly main window gets all the strings Im sending.
But if I comment out 'cout' it only gets the first one again and again.
It would seem that lstrcpy() only copies the first string if I comment out 'cout'.
I dont see the relation between the two.
Code:
DWORD WINAPI ShowProcess()
{
...
TCHAR* pItem = new TCHAR[MAX_PATH];
string str;
stringstream ss(s);
while (getline(ss, str, '?'))
{
lstrcpy(pItem, (TCHAR*)str.c_str());
PostMessage(hwnd, WM_USERDEFINED, (WPARAM)pItem, 0);
//cout << "item " << pItem << endl;
}
delete pItem;
return 0;
}
WndProc:
Code:
case WM_USERDEFINED:
SendMessage(hListBox, LB_ADDSTRING, (WPARAM)0, (LPARAM)(TCHAR*)wParam);
return 0;
Last edited by MasterDucky; June 27th, 2014 at 12:57 PM.
-
June 29th, 2014, 08:55 PM
#2
Re: PostMessage
PostMessage is asynchronous so you have no guarantees on when the data is read on the other thread. To see a change in this behavior, declare the string buffer inside the while loop (or use SendMessage as a test).
-
June 30th, 2014, 02:31 AM
#3
Re: PostMessage
It works with SendMessage but I was advised to use PostMessage from a thread instead.
It works also with declaring and deleting the string buffer in every loop but I thought it was an overkill.
Looks like it was designed this way then.
Thank you.
Last edited by MasterDucky; June 30th, 2014 at 03:15 AM.
-
June 30th, 2014, 02:57 AM
#4
Re: PostMessage
Originally Posted by MasterDucky
It works also with declaring and deleting the string buffer in every loop but I thought it was an overkill. Looks like there is no other way to program it.
It is not an "overkill". It is a standard way to implement the messaging from a worker thread. And I already pointed out in your other thread (maybe too short?) how to implement it.
Victor Nijegorodov
-
June 30th, 2014, 07:33 AM
#5
Re: PostMessage
Originally Posted by MasterDucky
It works with SendMessage but I was advised to use PostMessage from a thread instead.
It works also with declaring and deleting the string buffer in every loop but I thought it was an overkill.
Looks like it was designed this way then.
Thank you.
If you use PostMessage, then the receivng thread needs to delete the buffer not the sending thread (for the reasons I've decribed previously).
-
June 30th, 2014, 07:48 AM
#6
Re: PostMessage
Originally Posted by Arjay
If you use PostMessage, then the receivng thread needs to delete the buffer not the sending thread (for the reasons I've decribed previously).
Absolutely true!
However, with an exception: if PostMessage has failed then the sending thread must delete the buffer:
Code:
string str;
stringstream ss(s);
while (getline(ss, str, '?'))
{
TCHAR* pItem = new TCHAR[MAX_PATH];
lstrcpy(pItem, (TCHAR*)str.c_str());
if(!PostMessage(hwnd, WM_USERDEFINED, (WPARAM)pItem, 0))
delete[] pItem;
//cout << "item " << pItem << endl;
}
....
// receiver
case WM_USERDEFINED:
TCHAR* pItem = (TCHAR*)wParam ;
SendMessage(hListBox, LB_ADDSTRING, (WPARAM)0, (LPARAM)pItem);
delete[] pItem;
return 0;
Victor Nijegorodov
-
June 30th, 2014, 08:31 AM
#7
Re: PostMessage
Do not SEND messages from a thread to your main UI thread. This could potentially end up being a deadlock, but even if it isn't, it will effectively suspend the worker thread until the main thread has processed and returned from the message. This is why you should use PostMessage()
but in the case of post as here. you can't send a pointer and expect this to work "just like that". In this case, the message may not get processed until after you called the delete. The main thread will then end up accessing memory which is no longer valid, which could result in a crash, or the main thread processing incorrect data.
If you need to send a structure of data:
- either use a global interface structure shared by both threads. In this case, you'll need to synchronise access to this structure.
- allocate a structure, post the pointer, and delete the memory in the receiving thread.
- there's hybrid solutions of the above such as managing a ringbuffer (or some other type of structure depending on needs) that might have advantages over the above 2.
-
June 30th, 2014, 10:05 AM
#8
Re: PostMessage
I mention using SendMessage only as a test.
-
June 30th, 2014, 02:30 PM
#9
Re: PostMessage
Thanks for pointing this out.
I changed my code accordingly but since I cannot declare the pointer inside 'case WM_USERDEFINED:' I have to declare it outside of the 'switch (Msg)' and it's crashing that way.
Code:
LRESULT CALLBACK WndProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
TCHAR* pItem;
switch (Msg)
{
case WM_CREATE:
...
case WM_USERDEFINED:
pItem = (TCHAR*)wParam ;
SendMessage(hListBox, LB_ADDSTRING, (WPARAM)0, (LPARAM)pItem);
delete[] pItem;
return 0;
...
Last edited by MasterDucky; June 30th, 2014 at 02:41 PM.
-
June 30th, 2014, 03:39 PM
#10
Re: PostMessage
Yes, you can add variable inside case statement, add braces there to create local scope.
-
July 1st, 2014, 01:38 AM
#11
Re: PostMessage
Thanks, I did, it compiles but crashing.
This is what you meant?
Code:
case WM_USERDEFINED:
{
TCHAR * pItem = (TCHAR*)wParam;
SendMessage(hListBox, LB_ADDSTRING, (WPARAM)0, (LPARAM)pItem);
delete[] pItem;
}
It's working this way but Im not deleting the pointer:
Code:
case WM_USERDEFINED:
{
SendMessage(hListBox, LB_ADDSTRING, (WPARAM)0, (LPARAM)(TCHAR*)wParam);
}
Last edited by MasterDucky; July 1st, 2014 at 01:45 AM.
-
July 1st, 2014, 02:30 AM
#12
Re: PostMessage
Show your actual thread procedure code.
Victor Nijegorodov
-
July 1st, 2014, 04:12 AM
#13
Re: PostMessage
Thanks, I did, it compiles but crashing.
Have you used the debugger to trace through the code? On what line does the debugger determine it is 'crashing'? What are the contents of the variables when the crash occurs?When stepping through the code when does the value of variables differ from the expected values?
All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!
C++23 Compiler: Microsoft VS2022 (17.6.5)
-
July 1st, 2014, 06:43 AM
#14
Re: PostMessage
Originally Posted by VictorN
Show your actual thread procedure code.
Code:
string str;
stringstream ss(s);
while (getline(ss, str, '?'))
{
TCHAR* pItem = new TCHAR[MAX_PATH];
lstrcpy(pItem, (TCHAR*)str.c_str());
if(!PostMessage(hwnd, WM_USERDEFINED, (WPARAM)pItem, 0))
delete pItem;
}
Last edited by MasterDucky; July 1st, 2014 at 06:48 AM.
-
July 1st, 2014, 06:48 AM
#15
Re: PostMessage
Originally Posted by 2kaud
Have you used the debugger to trace through the code? On what line does the debugger determine it is 'crashing'? What are the contents of the variables when the crash occurs?When stepping through the code when does the value of variables differ from the expected values?
No, I havent. I use codeblocks with MSVC 2010 and single file debugging is not supported. I know its lame but I dont like to create a project for every little program I use.
Last edited by MasterDucky; July 1st, 2014 at 06:55 AM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|