//Client is my class that inherits from the Window class.
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
//LPTHREAD_START_ROUTINE
//Open the Client form in a new thread.
frmClient = new Client("wInternetClient", "Internet Test - Client");
frmClient->Position(225, 225);
frmClient->Size(220, 100);
frmClient->Style = WS_BORDER | WS_CAPTION;
frmClient->StyleEx = WS_EX_STATICEDGE;
frmClient->BackColor(212, 208, 200);
frmClient->Show();
}
//In the WM_COMMAND for the connect button I have the following line to create the thread
hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, 999);
🔒 Locked
Multi Threading?
Advertisement
Original Post
I am not quite sure what I have done wrong, but I have a window wrapper class to create windows. I create a new window class in a button click which then freezes both window's. I have used the same code in other programs and I have not ran into this problem. I am thinking that the message loop freezes the first window's message loop because the new window starts a message loop in the WM_COMMAND message. I am not quite sure, if that is the case, why it only does it in this application and not others, but it makes sense. Anyway, I tried to make a thread to call the new window creation and I am getting the following error: error C2664: 'CreateThread' : cannot convert parameter 3 from 'int (LPVOID)' to 'LPTHREAD_START_ROUTINE' I am not sure if I am doing something wrong somewhere, but if anyone can help, or point me in the right direction, I would appreciate it greatly. If more code is required I would be happy to post more.
Well, for the issue this all started with, I was creating a timer with SetTimer() right before creating the window. When I comment it out, everything runs fine. If I put the form in front of the SetTimer() function call does not get called until after I close the client form. I think threading is about the only way I can go about fixing this, but who knows I am wrong a lot. I still cannot figure out why I cannot run the thread. On MSDN they create a ThreadProc function with the same return value and parameter, and call CreateThread in the same manner as I am. However, I get the error as posted above. Thanks in advance.
Try this instead:
That might work.
DWORD WINAPI ThreadProc(LPVOID lpParameter){ //LPTHREAD_START_ROUTINE //Open the Client form in a new thread. frmClient = new Client("wInternetClient", "Internet Test - Client"); frmClient->Position(225, 225); frmClient->Size(220, 100); frmClient->Style = WS_BORDER | WS_CAPTION; frmClient->StyleEx = WS_EX_STATICEDGE; frmClient->BackColor(212, 208, 200); frmClient->Show();return ((DWORD)lpParameter); }That might work.
Thank you for the reply, I was too caught up in the error to remember to put the return value. However, it did not fix the problem, I am still getting:
error C2664: 'CreateThread' : cannot convert parameter 3 from 'DWORD (LPVOID)' to 'LPTHREAD_START_ROUTINE'
I think it was originally int(LPVOID) now it is back to DWORD. I appreciate the thought though, thanks again.
error C2664: 'CreateThread' : cannot convert parameter 3 from 'DWORD (LPVOID)' to 'LPTHREAD_START_ROUTINE'
I think it was originally int(LPVOID) now it is back to DWORD. I appreciate the thought though, thanks again.
I was reading up a little more on threads and I saw that CreateThread and CloseHandle can have problems and cause memory leaks. The recommended alternative was _beginthreadex(). However, in order to use it, you have to include . I include the file, yet now I get the error:
error C3861: '_beginthreadex': identifier not found, even with argument-dependent lookup
I cannot find anywhere that I need to include a .lib file or anything, only the header. I think I will keep looking into this version rather than the alternate CreateThread method.
error C3861: '_beginthreadex': identifier not found, even with argument-dependent lookup
I cannot find anywhere that I need to include a .lib file or anything, only the header. I think I will keep looking into this version rather than the alternate CreateThread method.
I've never had any problems with CreateThread. Just type cast it:
And I read that "small memory leak advisory" they talk about in the Win32 API, but I'm using two threads, both of which call fread from the standard C libraries, and no memory leaks. Not even small ones. ;)
Just don't call ExitThread. Let the thread run out, or put a boolean to tell the thread to "exit" by passing it through the parameter. Either way, never order the thread to exit.
CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadProc,NULL,0,&someInt);And I read that "small memory leak advisory" they talk about in the Win32 API, but I'm using two threads, both of which call fread from the standard C libraries, and no memory leaks. Not even small ones. ;)
Just don't call ExitThread. Let the thread run out, or put a boolean to tell the thread to "exit" by passing it through the parameter. Either way, never order the thread to exit.
Thank you very much for your reply Nychold: I did try to cast the function to LPTHREAD_START_ROUTINE, it gave me an error telling me I could not convert the function to it.
error C2440: 'type cast' : cannot convert from 'overloaded-function' to 'LPTHREAD_START_ROUTINE'
Thank you for the thought though.
error C2440: 'type cast' : cannot convert from 'overloaded-function' to 'LPTHREAD_START_ROUTINE'
Thank you for the thought though.
I don't think I am overloading it, and if I am, I am not doing it on purpose. Could it be thinking that I am because it is in a class? (probably dumb question).
Is there a ThreadProc function already created or something? Sorry for the silly questions, I am just pretty confused.
Is there a ThreadProc function already created or something? Sorry for the silly questions, I am just pretty confused.
Yep, that'll do it. See, every call from a class has a "hidden" parameter in it, which carries "this" information. That's how C++ knows where it is. The only way to get around this is to make it static, and pass as a parameter your class. Here's (one of) mine:
And no, it's not silly. I've been in a similar situation before numerous times. ;)
//...inside TAudioObject hLoad=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)threadLoad, this,0,&threadID); //... static DWORD threadLoad(void *param) { TAudioObject *obj=(TAudioObject *)param; // Thread must load 1 buffer, set the ready state // and continue to load the other buffers with a // short sleep state (50 milliseconds) between loads alSourcei(obj->sourceID,AL_LOOPING,AL_FALSE); for (int i=0;i<BUFFER_COUNT;i++) { switch (obj->type) { case AUDIO_WAV: obj->StreamWAV(obj->bufferID); break; case AUDIO_OGG_VORBIS: obj->StreamOGG(obj->bufferID); break; } alSourceQueueBuffers(obj->sourceID,1,&obj->bufferID); obj->ready=true; SleepEx(100,true); } obj->hLoad=NULL; obj->threadID=0; return 0; };And no, it's not silly. I've been in a similar situation before numerous times. ;)
Thank you very much for helping me out as much as you have. I changed it to static, and now it is not giving me the errors.
I do have another question for you however. I am passing 999 as the last parameter to the CreateThread function which I am sure isn't the best thing. I noticed in yours you pass &threadID. What exactly is this used for?
Thank you again, I really appreciate your patience and help.
I do have another question for you however. I am passing 999 as the last parameter to the CreateThread function which I am sure isn't the best thing. I noticed in yours you pass &threadID. What exactly is this used for?
Thank you again, I really appreciate your patience and help.
The return value from the thread function. At least, I think that's what it's for. I dunno, I've never really used it. ;) Even if you don't need it, you need to have a place for it.
EDIT: According to Schildt's Windows 95 Programming in C/C++, it's a unique identifier for the thread. Which to me, seems silly because CreateThread already returns a more useful unique ID...the HANDLE. Oh well. Like I said, I've never used it.
EDIT: According to Schildt's Windows 95 Programming in C/C++, it's a unique identifier for the thread. Which to me, seems silly because CreateThread already returns a more useful unique ID...the HANDLE. Oh well. Like I said, I've never used it.
Yeah, you are correct. I was getting errors with my 999 idea. It is actually working now (to a degree). The new form is created, but now the other form recieves no messages. It doesn't paint or anything, and even after the new form is closed it stays "frozen". But that has nothing to do with CreateThread, I am probably not using CloseHandle() in the right place, or something. I will look into it.
Thanks again, this is starting to make a little sense.
Thanks again, this is starting to make a little sense.
Anonymous:
What I am "trying" to do is learn winsock, and I saw, what looks like, a decent tutorial on planetsourcecode.com. It shows how to create a server/listener and how to make something connect to it. I thought I would make a server form and a client form therefor (I guess/think) would want 2 message pumps? He mentioned that the accept function should be in a loop of some sort, but a while loop would freeze.
I figured I would put it in a timer instead. I figured out the reason for the "freezing" (to a degree). The problem is caused when I run the SetTimer function. For some reason when I create a timer on the server form, and open the client form, the server form freezes.
I refer to the window as a form because I am a VB nerd. sorry if it causes confusion.
I do know my design is not the best and there is a lot I could improve. I did not know only one message loop was needed in c++, I thought each form/window needed it's own to handle the messages, although as I am writing this it makes sense one message loop/pump/whatever could handle multiple windows because it has the HWND parameter which could handle multiple windows. I will look into using only one, it might fix some of my problems.
If you have any idea on why the SetTimer would cause this, or if it could be because of the multiple message pumps or what not, I would be glad to search for a better method. I have never been too fond of multithreading, it can turn into a huge jumbled mess. Thank you for the advice and ideas, hopefully I can figure out a better way to do this.
What I am "trying" to do is learn winsock, and I saw, what looks like, a decent tutorial on planetsourcecode.com. It shows how to create a server/listener and how to make something connect to it. I thought I would make a server form and a client form therefor (I guess/think) would want 2 message pumps? He mentioned that the accept function should be in a loop of some sort, but a while loop would freeze.
I figured I would put it in a timer instead. I figured out the reason for the "freezing" (to a degree). The problem is caused when I run the SetTimer function. For some reason when I create a timer on the server form, and open the client form, the server form freezes.
I refer to the window as a form because I am a VB nerd. sorry if it causes confusion.
I do know my design is not the best and there is a lot I could improve. I did not know only one message loop was needed in c++, I thought each form/window needed it's own to handle the messages, although as I am writing this it makes sense one message loop/pump/whatever could handle multiple windows because it has the HWND parameter which could handle multiple windows. I will look into using only one, it might fix some of my problems.
If you have any idea on why the SetTimer would cause this, or if it could be because of the multiple message pumps or what not, I would be glad to search for a better method. I have never been too fond of multithreading, it can turn into a huge jumbled mess. Thank you for the advice and ideas, hopefully I can figure out a better way to do this.
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement