I'm trying to create a worker thread in a class called ClientManager, but I can't get access to AfxGetMainWnd() from the new CWinThread, i.e:
UINT ClientManager::WorkerThreadProc( LPVOID param ){
ClientManager *pThis = reinterpret_cast<ClientManager*>(param);
return pThis -> DoThreadJob();
}
UINT ClientManager::DoThreadJob(){
createClientSession("1");
return 0;
}
void ClientManager::createThread(){
m_clientManagerThread = AfxBeginThread(WorkerThreadProc,this,0,0,0,NULL);
}
void ClientManager::createClientSession(CString clientID){
if (AfxGetMainWnd()->GetSafeHwnd()== NULL){
_cprintf("NULL");
}
}
Output: NULL
AfxGetMainWnd()->GetSafeHwnd() works in the main thread.
Thanks!
AfxGetApp()->GetMainWnd() works in threads.
No need to store the window handle in a member of ClientManager.
The documentation says:
If AfxGetMainWnd is called from the application's primary thread, it returns the application's main window according to the above rules. If the function is called from a secondary thread in the application, the function returns the main window associated with the thread that made the call.
So you need to make the call from the main thread. Do this just before you call AfxBeginThread and store the resulting window handle in a member of ClientManager. Then your thread can gain access to the window handle via its ClientManager reference.
Related
I have a thread which creates a hidden window for the purpose of receiving WinAPI messages based on power state. I need to get the HWND of the created window from the thread so that I can throw a WM_QUIT message to close the window and end the thread gracefully:
Main:
HWND hiddenWindowHandle = NULL;
HANDLE PowerWindowThreadHandle = (HANDLE)_beginthreadex(0, 0, &windowsPowerThread, (void*)&hiddenWindowHandle, 0, 0);
Thread:
unsigned int __stdcall windowsPowerThread(void* data)
{
HWND hiddenWindowHandle = createHiddenWindow();
HWND hwHandle = *(HWND*)data;
hwHandle = hiddenWindowHandle;
...
The problem is that the hiddenWindowHandle is not being updated with the generated HWND.
I have verified in the thread that it's being created, and I've verified that I'm not trying to access the handle before the thread creates it.
What am I missing here?
Your code lacks the necessary synchronization. What you have here is a data race. Thus, what you get is strictly undefined behavior. What will most likely happen is that the compiler simply does not re-fetch the value of hiddenWindowHandle from memory in every iteration of the loop, since it can simply assume that the value does not change. One possible solution would be to make hiddenWindowHandle an std::atomic and have the main thread perform a busy wait until the value changes from NULL. Alternatively, you could put all access to the shared variable into a critical section locked by a mutex, or use a condition variable to wait for the value to be available.
Edit based on comments:
So if I understand your code correctly, the thread that creates the window receives a pointer to the result variable in the form of a void* and then tries to communicate the result like so:
unsigned int __stdcall windowsPowerThread(void* data)
{
…
HWND hwHandle = *(HWND*)data;
hwHandle = hiddenWindowHandle;
…
}
There's two problems here. First of all, data doesn't point to an HWND, it points to an std::atomic<HWND> now, so you already have undefined behavior there. The main problem, and probably the explanation why your original code didn't just happen to work anyways, despite the data race, is that you create a new local HWND called hwHandle. This local variable is initialized with the value of whatever data points to. You then assign your result to that local variable, but never to the actual result variable.
What you want to do is more something along the lines of
unsigned int __stdcall windowsPowerThread(void* data)
{
…
HWND hiddenWindowHandle = createHiddenWindow(…);
*static_cast<std::atomic<HWND>*>(data) = hiddenWindowHandle;
…
}
You may also want to consider using std::thread instead of the raw CRT functions.
I am calling a library function which also need a callback function as its only argument. It is time consuming function and the callback is called frequently to pass messages to the client (my application) to display. The problem is I want to copy the message and pass it onto the main thread for display but because it is callback function, I see no other way but to use globals to do that and that's what I am trying to avoid/make better.
The callback is static member function of my CTestDlg which alrady has m_hWnd member where I want to post the messages. However for the sake of callback I have yet defined another static g_hWnd member so my callback can access it and post message to it. This part doesn't look very nice to me but my callback routine is collecting messages wonderfully.
My callback function is the following
void CTestDlg::OnNotify (int code, const char * msg)
{
char * message = NULL; // to copy the message
message = new char[ strlen( msg) + 1 ]();
strcpy_s( message, strlen(msg) +1, msg );
PostMessageA( g_hWnd, ID_NOTIFY_MSG, code, (LPARAM) message );
}
I am running the library call in a separate thread and because it is callback to that function, it also runs in the same thread. Is there a better way to change hand in this callback function and pass the message to main thread or a particularly window to display?
If your callback is a static method, it has no access to instance data, so you must store your state data (the main window handle, in your case) in a static or global variable.
You can move the handle from a global variable to a static CTestDlg::s_hWnd variable.
I try to write a Multithreading WIN32 Application in C++, but due to i get difficulties.
One of the Window Procedure creates a Thread, which manages the output of this window. If this Window Procedure receives a message (from the other Window Procedures), it should transmit it to their Thread. At the beginning i worked with the _beginthread(...) function, what doesn't work.
Then i tried it with the CreateThread(...) function, and it worked? What did i do wrong?
(My English isn't so good, i hope you understand my problem)
Code with CreateThread(...):
DWORD thHalloHandle; // global
HWND hwndHallo; // Hwnd of WndProc4
...
LRESULT APIENTRY WndProc4 (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static PARAMS params ;
switch (message)
{
case WM_CREATE: {
params.hwnd = hwnd ;
params.cyChar = HIWORD (GetDialogBaseUnits ()) ;
CreateThread(NULL, 0, thHallo, ¶ms, 0, &thHalloHandle);
return 0 ;
}
...
case WM_SPACE: {
PostThreadMessage(thHalloHandle, WM_SPACE, 0, 0);
return 0;
}
...
}
Code with _beginthread(...):
...
case WM_CREATE: {
params.hwnd = hwnd ;
params.cyChar = HIWORD (GetDialogBaseUnits ()) ;
thHalloHandle = (DWORD)_beginthread (thHallo, 0, ¶ms) ;
return 0;
}
...
case WM_SPACE: {
PostThreadMessage(thHalloHandle, WM_SPACE, 0, 0);
return 0;
}
...
thHallo for CreateThread:
DWORD WINAPI thHallo(void *pvoid)
{
static TCHAR *szMessage[] = { TEXT(...), ...};
// Some Declaration
pparams = (PPARAMS) pvoid;
while(!pparams->bKill)
{
MsgReturn = GetMessage(&msg, NULL, 0, 0);
hdc = GetDC(pparams->hwnd);
if(MsgReturn)
{
switch(msg.message)
{
// case....
}
}
}
return 0;
}
thHallo for _beginthread(...):
void thHallo(void *pvoid)
{
...
// The Same like for CreateThread
...
_endthread();
}
The _beginthread/ex() function is proving to be radically difficult to eliminate. It was necessary back in the previous century, VS6 was the last Visual Studio version that required it. It was a band-aid to allow the CRT to allocate thread-local state for internal CRT variables. Like the ones used for strtok() and gmtime(), CRT functions that maintain internal state. That state must be stored separately for each thread so that the use of, say, strtok() in one thread doesn't screw up the use of strtok() in another thread. It must be stored in thread-local state. _beginthread/ex() ensures that this state is allocated and cleaned-up again.
That has been worked on, necessarily so when Windows 2000 introduced the thread-pool. There is no possible way to get that internal CRT state initialized when your code gets called by a thread-pool thread. Quite an effort btw, the hardest problem they had to solve was to ensure that the thread-local state is automatically getting cleaned-up again when the thread stops running. Many a program has died on that going wrong, Apple's QuickTime is a particularly nasty source of these crashes.
So forget that _beginthread() ever existed, using CreateThread() is fine.
There's a serious problem with your use of PostThreadMessage(). You are used the wrong argument in your _beginthread() code which is why it didn't work. But there are bigger problems with it. The message that is posted can only ever be retrieved in your message loop. Which works fine, until it is no longer your message loop that is dispatching messages. That happens in many cases in a GUI app. Simple examples are using MessageBox(), DialogBox() or the user resizing the window. Modal code that works by Windows itself pumping the message loop.
A big problem is the message loop in that code knows beans about the messages you posted. They just fall in the bit-bucket and disappear without trace. The DispatchMessage() call inside that modal loop fails, the message you posted has a NULL window handle.
You must fix this by using PostMessage() instead. Which requires a window handle. You can use any window handle, the handle of your main window is a decent choice. Better yet, you can create a dedicated window, one that just isn't visible, with its own WndProc() that just handles these inter-thread messages. A very common choice. DispatchMessage() can now no longer fail, solves your bug as well.
Your call to CreateThread puts the thread ID into thHalloHandle. The call to _beginthread puts the thread handle into thHalloHandle.
Now, the thread ID is not the same as the thread handle. When you call PostThreadMessage you do need to supply a thread ID. You only do that for the CreateThread variant which I believe explains the problem.
Your code lacks error checking. Had you checked for errors on the call to PostThreadMessage you would have found that PostThreadMessage returned FALSE. Had you then gone on to call GetLastError that would have returned ERROR_INVALID_THREAD_ID. I do urge you to include proper error checking.
In order to address this you must first be more clear on the difference between thread ID and thread handle. You should give thHalloHandle a different name: thHalloThreadId perhaps. If you wish to use _beginthread you will have to call GetThreadId, passing the thread handle, to obtain the thread ID. Alternatively, use _beginthreadex which yields the thread ID, or indeed CreateThread.
Your problem is that you need a TID (Thread Identifier) to use PostThreadMessage.
_beginthread doesn't return a TID, it return a Thread Handle.
Solution is to use the GetThreadId function.
HANDLE hThread = (HANDLE)_beginthread (thHallo, 0, ¶ms) ;
thHalloHandle = GetThreadId( hThread );
Better Code (see the documentation here)
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, thHallo, ¶ms, 0, &thHalloHandle ) ;
I try to pass a structure as a parameter.
Global structure:
struct ThreadParams
{
HWND window;
LIB::ServiceContainer* mrt;
};
In the main thread:
ThreadParams threadparams;
threadparams.window = (HWND) GetSafeHwnd();
threadparams.mrt = m_rt;
CWinThread* pthread1;
pthread1 = (CWinThread*) AfxBeginThread(Thread1,(LPVOID)&threadparams,THREAD_PRIORITY_NORMAL,0,0,0);
Outside the class:
UINT Thread1(LPVOID lp)
{
ThreadParams* threadparams = (ThreadParams*) lp;
HWND hmainWindow = threadparams->window;
LIB::ServiceContainer* m_rt = threadparams->mrt;
}
Although it compiles fine, I get an error at runtime (it is an unexpected error) and I guess that I mess up with the pointer m_rt. Do you see any obvious mistakes?
ThreadParams threadparams;
Note that if it is a local variable, and the function which declares it returns after creating the thread, then the thread refers to an object which doesn't exist anymore, as the local variable gets destroyed when the function returns. If that is the case, then create a new instance using new instead as:
ThreadParams * pthreadparams = new ThreadParams();
and pass it to the thread, so that it will exist even if the function which creates the thread returns. Of course, when you're done with it, you've to delete it manually.
You cannot safely access a local variable allocated in a different thread in most cases. By the time Thread1 starts up, the structure has likely already gone out of scope in the main thread. You should find another way, such as allocating the parameters with new in the main thread and deleting them when you're done with them in Thread1.
Inside my app, I want to send a message to a dialog from a different thread.
I want to pass an std::exception derived class reference to the dialog.
Something like this:
try {
//do stuff
}
catch (MyException& the_exception) {
PostMessage(MyhWnd, CWM_SOME_ERROR, 0, 0); //send the_exception or the_exception.error_string() here
}
I want to receive the message in my dialog and show the error that is in the_exception.error_string()
LPARAM CMyDlg::SomeError(WPARAM, LPARAM)
{
show_error( ?????
return 0;
}
passing the std::string the_exception.error_string() using PostMessage would also be ok, I guess.
You can't pass the address of the string in PostMessage, since the string is probably thread-local on the stack. By the time the other thread picks it up, it could have been destroyed.
Instead, you should create a new string or exception object via new and pass its address to the other thread (via the WPARAM or LPARAM parameter in PostMessage.) The other thread then owns the object and is responsible for destroying it.
Here is some sample code that shows how this could be done:
try
{
// do stuff
}
catch (const MyException& the_exception)
{
PostMessage(myhWnd, CWM_SOME_ERROR, 0, new std::string(the_exception.error_string));
}
LPARAM CMyDlg::SomeError(WPARAM, LPARAM lParam)
{
// Wrap in a unique_ptr so it is automatically destroyed.
std::unique_ptr<std::string> msg = reinterpret_cast<std::string*>(lParam);
// Do stuff with message
return 0;
}
As long as you are within a process simply passing a void* pointer and some care on object lifetime are enough.
If is SendMessage you can pass it in LPARAM as a void* cast, and the client uncast it back to your string type. Because SendMessage is synchronous, you are safe:
If the specified window was created by
the calling thread, the window
procedure is called immediately as a
subroutine. If the specified window
was created by a different thread, the
system switches to that thread and
calls the appropriate window
procedure. Messages sent between
threads are processed only when the
receiving thread executes message
retrieval code. The sending thread is
blocked until the receiving thread
processes the message
If you want to use PostMessage then you'll have to do an explicit hand off because the call is asynchronous: make a copy of the string on the heap and by calling the PostMessage you have passed the delete responsability to the calee (the dialog).
If you go out of process (MyhWnd belongs to a different process) then is a whole different story and you'll have to marshal your message into something like a global atom.
As long as you know that your window (or instance of CMyDlg) will still be around after posting the message you could simply store the error string in a member variable and read from this in your message handler.