|
Thanks for the response. I noticed that there are three PostMessage functions. One is in the Windows API, one is a member of the class CWindow and the other is a member of the class CWnd. Since I want the message to be processed by the GUI thread, your advice on PostMessage vers SendMessage is right on target. However, I am not sure which of the three PostMessage functions to call. I am thinking that I should call CWnd::PostMessage(). Does it matter which one I call?
I would also like to say that the codeproject has quickly become one of my favorite websites due to people like Code-o-mat.
Bob
|
|
|
|
|
FYI - It is NOT true that SendMessage() called from a different thread the window was
created on calls the windowproc on the different thread. If it's called from a different
thread, that thread is blocked and the WindowProc is called on the thread the window was created on.
So you can use ::SendMessage() from a different thread than the window was created on, but be
aware the blocking nature is different than the non-blocking nature of ::PostMessage().
Also, if those variables you are incrementing are integers <= the native integer size
for the processor you're running on, then the increment operation is most likely atomic
so it is thread safe. The variables should be marked as volatile, however, or better yet,
use interlocked increment operations as mentioned by Luc.
The Invalidate calls are NOT thread safe if "this" is a CWND (or derived) pointer.
If you end up locking the operations, you may want to use a critical section instead of a mutex.
You only need a mutex if other processes need synchronized access...
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Mark Salsbery wrote: FYI - It is NOT true that SendMessage() called from a different thread the window was
created on calls the windowproc on the different thread. If it's called from a different
thread, that thread is blocked and the WindowProc is called on the thread the window was created on.
So you can use ::SendMessage() from a different thread than the window was created on, but be
aware the blocking nature is different than the non-blocking nature of ::PostMessage().
I didn't know that, thanks for the information Mark, i'm sorry for the misleading post. Till this point i was completely sure SendMessage would directly call the handler. Guess i'm an idiot, but we have a saying here, "a good priest learns till death".
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
|
|
|
|
|
Heh no problem I personally wouldn't be here if I didn't learn
stuff all the time.
This topic gets even trickier when you throw MFC into the mix, where some
operations may be thread safe, some aren't thread safe, and none are guaranteed
to always be thread safe. Your signature tag-line comes into play pretty quickly.
Cheers!
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Afaik CWnd::PostMessage doesn't do anything else but calls the API PostMessage specifying the handle of the window it represents, so there's not much difference between those two, however, if we stick to the general rule of not handing CWnd objects (pointers) over to different threads, i'd say, go for the api call. It's also somewhat safer since if your CWnd gets for some reason deleted then if a thread tries to call its CWnd::PostMessage it will give you the dreaded Access Voilation error. However, if you specify an invalid handle to the API PostMessage it will check that handle to see if a window with that handle exists and if not, then it will simply not post any message to it, thus, no crash. I have no idea about CWindow::PostMessage.
Alternatively you could use PostThreadMessage to post thread messages, these work almost the same way as window messages but they are not targeted at specific window procedures (their target hWnd will be NULL). If you use window messages, note, that in certain circumstances they can get lost. For example, when the user starts dragging a window in the GUI thread to move it around, a "custom" message loop starts up which filters out and throws away certain messages (i guess the reason for this is to avoid nasty situations like crashes, but ask Microsoft about that), so it could happen that while the user moves your window, the messages coming from your threads simply disappear in a black hole never to be seen again. However, this does not seem to happen with thread messages.
BobInNJ wrote: I would also like to say that the codeproject has quickly become one of my favorite websites due to people like Code-o-mat.
Thanks, you are making me blush.
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
|
|
|
|
|
hi,
these days i want to learn CStringArray and CTypedPtrList,so i creat a listbox for this:
private:
CTypedPtrList < CPtrList,CStringArray* > m_ptrListAllListItem;
void CListboxstrDlg::OnBtnAddlistitem()
{
static int sItemIndex = 0;
CString str;
str.Format("[listitem%d]",sItemIndex++);
int nSel = m_list.AddString(str);
CStringArray* pstrArry = new CStringArray [1];
ASSERT(pstrArry != NULL);
TRACE("------the new pstrArry addr is:%x \n",pstrArry);
pstrArry->Add(str);
m_ptrListAllListItem.AddTail((CStringArray*)pstrArry);
m_list.SetCurSel(m_list.GetCount()-1);
}
void CListboxstrDlg::OnBtnDellistitem()
{
int nSel = m_list.GetCurSel();
if (LB_ERR == nSel)
{
return;
}
POSITION pos;
pos = m_ptrListAllListItem.FindIndex(nSel);
if (pos)
{
CStringArray* ptStrArry;
ptStrArry = (CStringArray*)m_ptrListAllListItem.GetAt(pos);
TRACE("the ptStrArry addr is %x \n",ptStrArry);
m_ptrListAllListItem.RemoveAt(pos);
delete ptStrArry;
m_list.DeleteString(nSel);
m_list.SetCurSel(nSel - 1);
}
}
thank u very much!!
modified on Thursday, December 25, 2008 10:07 PM
|
|
|
|
|
okay,i got it!
delete ptStrArry;
->
delete [] ptStrArry;
|
|
|
|
|
I am looking at your post and the response you have already received. If the problem you are having is a compile time error then making the change already suggested is the way to go. However, from your description of the problem, it looks more like a run time problem. If so, making the change suggested is still a good idea but I doubt it would solve your problem.
What you are telling me is that you are allocated a valid pointer from new and then when you go to delete it, the delete fails. I cannot be 100% sure that you have not found a bug in delete but I am nearly 100% sure that you have not.
Typically delete does not return the space back to the operating system but instead puts the freed buffer on a linked list. This linked list can be corrupted in one of the following ways:
1) deleting the same pointer twice.
2) deleting space not allocated from new
3) indirecting a pointer that just happens to be pointed into this linked list.
Doing any of these can result in unexpected problems at run time. A variation on number 3 would be where you allocate a pointer of 10 bytes but then write to byte 11 or byte 12. This could also lead to the problem you are having.
I hope I have helped you and feel free to ask a follow up question.
Good Luck
|
|
|
|
|
thank u for your reply. i changed the codes like this:
delete ptStrArry;
-->delete [] ptStrArry;
this can resolve the question.
but when i test the codes, for example, run the function OnBtnLoop like this:
void CListboxstrDlg::OnBtnLoop()
{
TRACE("-------------start loop! \n");
for (int i = 0; i < 10000; i++)
{
OnBtnAddlistitem();
}
for (i--; i >= 0; i--)
{
OnBtnDellistitem();
}
TRACE("-------------finish loop! \n");
}
i found the memory used from 4668k to 4876k, and when i run the funcion again, the memory used form 4876k to 5384k. so i think the program must be something wrong...
but until now, i havenot found it.....
but another question
modified on Friday, December 26, 2008 7:24 AM
|
|
|
|
|
btw:
if i donot run the codes in the debug mode(Ctrl + F5), the memory used is normal...
so, why in debug mode(F5), the memory used from 4668k to 4876k,or from 4876k to 5384k?
i really donot know the reason...
anybody can explain this for me? thank u!
|
|
|
|
|
In the debug version of the C++ runtime it allocates memory differently from the release version.
In the debug version, when you allocate new memory, the runtime also allocates a full page of extra memory before and after the buffer you have called for.
It fills these extra pages with the value CD. These are called guard pages. They are used for checking to see if your program has written outside the bounds of the memory you allocated.
This is why your debug version uses more memory than the release version.
|
|
|
|
|
thank u for your reply.
but i think what i said is not clear.
my meaning is that the two ways are both in debug version:Ctrl+F5(not debug mode) and F5(debug mode), but not in release version.
|
|
|
|
|
I want to create a window in a thread. Instead of deriving a class from CWinThread and setting the m_pMainWnd variable, can I just create a worker thread and create the window in the controlling function. Then could I post messages to the window, and the resulting functions calls would occur in the new thread?
|
|
|
|
|
That's the way I've always done it. Unless there is something I'm unaware of, that seems to be the way to go.
|
|
|
|
|
Hi, I went to project properties, linker input and added the following library: "winmm.lib", then I clicked on resouces in the solution explorer and clicked on add existing resource and added a .wav file.. Then I manually created a resource script that I will show you here:
#include "Resource.h"
IDI_FISHL ICON "Res\\fishicon.ico"
IDI_FISHS ICON "Res\\fishiconsm.ico"
IDB_BACKGROUND BITMAP "Res\\background.bmp"
IDB_FISH BITMAP "Res\\fish.bmp"
IDB_BUBBLE BITMAP "Res\\bubble.bmp"
IDW_BUBBLES WAVE "Res\\bubbles.wav"
and here is the resource.h file
#define IDI_FISHL 1000
#define IDI_FISHS 1001
#define IDB_FISH 2000
#define IDB_BACKGROUND 2001
#define IDB_BUBBLE 2002
#define IDW_BUBBLES 3000
Okay and this is the error the compiler gives me: 1>.\Resource.h(21) : fatal error RC1004: unexpected end of file found
PLEASE PLEASE HELP ME!!!
|
|
|
|
|
This is what MSDN says about that error:
This error can be caused by missing linefeed and carriage return characters on the last line of a text file.
Try adding a few blank lines at the end of the resource.h file, making sure that each line has a CRLF.
|
|
|
|
|
I added some blank lines and that didn't work.. But I did take that last line and put in the front of the file and it worked okay.
|
|
|
|
|
Glad to hear it worked out.
Happy Holidays!
|
|
|
|
|
Hey guys...
I got a string from a web page. I wanted to match a string if it exists. Actually my search string doesnot include any reg-ex characters. (Pls do not advise me to use search string methods...)
Anyway.... When I call rgx.Match method it returns TRUE and marks start and end string (I saw it in debug mode) BUT m_uNumGroups variable is set to 0. So I could not get matched piece.. I got error......
So why this happens? Regex says there's a match but there are no match groups....
Thank you all...
|
|
|
|
|
|
The m_uNumGroups shows how many captures you have from using grouping characters (i.e. brackets) in the regexp.
e.g. If I match "abc" with the regexp "([a-z])(.+)" it'll match and I'll get two groups, the first containing "a" and the second containing "bc". If I match "abc" with the regexp "[a-z].+" (i.e. same as the first but without the brackets) it'll still match, but I'll get no groups.
So - I suspect your regexp has no brackets? Difficult to say without seeing it...
|
|
|
|
|
we have one dedicate m/c to do logging stuff only.The process which is doing logging get hanged for 5-15 min. By analyzing the problem,I have found that it hanged on closing the file.it hangs on API "fclose".It happens when we have file large log file(in between of 500MB to 1.3GB).
I have already tried following things:
1) just doing fflush before flose(fflush has been done successfully and very quickly)
2) to make sure this file has not been used by any other process,I tried to rename the file when fclose is in hanging state.I am able to do this.
3) After 500MB,I tried to close and open file again after each 50MB.Still hangs every time.
This problem is happening only on live system.It is not getting on my local m/c.I am not finding any reason now.
Do anyone have some suggestion or idea related to this problem?
Regards,
Vishal Soni
modified on Thursday, December 25, 2008 1:00 PM
|
|
|
|
|
How to use CAsyncSocket objects in CWinThread object Safely?!
(the tread should use ActiveX controls - a CListCtrl in the main CDialog dialogbox- to show notifications and events)
- i dint use threads in a first version, instead i used a RoundRobin Algo to answer the clients! but the server was slow
so now i need to get the threads work!
thank's in advance...
|
|
|
|
|
Mind Machine wrote: How to use CAsyncSocket objects in CWinThread object Safely?
The same way you'd use any other objects in a thread safely.
Do you have a specific question? If you don't know how to write
multi-threaded code, that would probably be a great place to start.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
well Mark, my problem exactly is;
when is, in my thread, when i use th listening socket wich is a member of my main dialog to accept connections; this last calls the runtime to terminate it, which is an unusual way to end a dialog! and also my thread cant call any ActiveX control! (assertion fails!!)
|
|
|
|