Peeking into the message queue of another thread
-
After reading the API for PeekMessage, this only works with the message queue of the current thread. I have tried using this function in another thread, and passing the HWND of the MainApp´s window and this does not work. (If I have understood the MSDN correctly, this is the correct behavour). Is it possible to peek into the message queue of another thread?. For example UINT ThreadProc(LPVOID pVoid){ MSG msg; struct_t* pS = reinterpret_cast(pVoid); HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, _T("NAMED_EVENT"); ASSERT(NULL != hEvent); if(NULL == hEvent){ return 1; } DWORD dwWait = 0; BOOL bContinue = TRUE; while(bContinue){ dwWait = WaitForSingleObject(hEvent, 1000); switch(dwWait){ case WAIT_TIMEOUT: while(::PeekMessage(&msg, pS->hWnd, NULL, NULL, PM_NOREMOVE)){ bContinue = pS->pThread->PumpMessage(); } break; case WAIT_OBJECT_0: bContinue = FALSE; break; } } return 0; } struct_t is just an example of what I am passing. The HWND of the main application window, and pThread the CWinThread of the main application. Any suggestions would be appriciated... Thanks bum... and I thought I´d got rid of all the bugs :(
-
After reading the API for PeekMessage, this only works with the message queue of the current thread. I have tried using this function in another thread, and passing the HWND of the MainApp´s window and this does not work. (If I have understood the MSDN correctly, this is the correct behavour). Is it possible to peek into the message queue of another thread?. For example UINT ThreadProc(LPVOID pVoid){ MSG msg; struct_t* pS = reinterpret_cast(pVoid); HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, _T("NAMED_EVENT"); ASSERT(NULL != hEvent); if(NULL == hEvent){ return 1; } DWORD dwWait = 0; BOOL bContinue = TRUE; while(bContinue){ dwWait = WaitForSingleObject(hEvent, 1000); switch(dwWait){ case WAIT_TIMEOUT: while(::PeekMessage(&msg, pS->hWnd, NULL, NULL, PM_NOREMOVE)){ bContinue = pS->pThread->PumpMessage(); } break; case WAIT_OBJECT_0: bContinue = FALSE; break; } } return 0; } struct_t is just an example of what I am passing. The HWND of the main application window, and pThread the CWinThread of the main application. Any suggestions would be appriciated... Thanks bum... and I thought I´d got rid of all the bugs :(
TRY ATTACHING THE HWND TO A CWnd object. so you can get the message queue.
CWnd wnd;
wnd.Attach(hwnd);
......
wnd.Detach();SaRath.
"It is your attitude, not your aptitude, that determines your altitude - Zig Ziglar." My Blog | Understanding State Pattern in C++ -
TRY ATTACHING THE HWND TO A CWnd object. so you can get the message queue.
CWnd wnd;
wnd.Attach(hwnd);
......
wnd.Detach();SaRath.
"It is your attitude, not your aptitude, that determines your altitude - Zig Ziglar." My Blog | Understanding State Pattern in C++No, I have tried that and it does not work. The PeekMessage (I think) is still looking in the current threads message queue (i.e. the worker thread). This is not the result I need. I have tried also the following: BOOL CMainFrame::FudgeForceRedrawOfMainWindow(){ MSG msg; while (::PeekMessage(&msg, NULL, // pump message until none NULL, NULL, PM_NOREMOVE)) // are left in the queue { AfxGetThread()->PumpMessage(); } return TRUE; } A function to see if there are any messages pending in the App´s message queue BOOL CMainFrame::IsMessageQueueEmpty(){ // QS_ALLINPUT // *********** DWORD dwState = GetQueueStatus(QS_ALLINPUT); if(HIWORD(dwState) == QS_ALLEVENTS){ return FALSE; } // Nothing of interest // ****************** return TRUE; } Calling this function in my worker thread instead of ::PeekMessage(....) i.e. in the ThreadProc Changed the structure passed to include a CMainFrame pointer pxFrame ... case WAIT_TIMEOUT: while(!pxFrame->IsMessageQueueEmpty()){ pxFrame->FudgeForceRedrawOfMainWindow(); } break; ... When called from the tread, the FudgeForceRedrawOfMainWindow() function never has any messages in the queue (in the PeekMessage(...) and therefore the PumpMessage() is never called. HOWEVER if I call the FudgeForceRedrawOfMainWindow()in the same thread as the MainApp ( in lengthy interations) it works fine! I´m a bit stumped about this.... bum... and I thought I´d got rid of all the bugs :(
-
No, I have tried that and it does not work. The PeekMessage (I think) is still looking in the current threads message queue (i.e. the worker thread). This is not the result I need. I have tried also the following: BOOL CMainFrame::FudgeForceRedrawOfMainWindow(){ MSG msg; while (::PeekMessage(&msg, NULL, // pump message until none NULL, NULL, PM_NOREMOVE)) // are left in the queue { AfxGetThread()->PumpMessage(); } return TRUE; } A function to see if there are any messages pending in the App´s message queue BOOL CMainFrame::IsMessageQueueEmpty(){ // QS_ALLINPUT // *********** DWORD dwState = GetQueueStatus(QS_ALLINPUT); if(HIWORD(dwState) == QS_ALLEVENTS){ return FALSE; } // Nothing of interest // ****************** return TRUE; } Calling this function in my worker thread instead of ::PeekMessage(....) i.e. in the ThreadProc Changed the structure passed to include a CMainFrame pointer pxFrame ... case WAIT_TIMEOUT: while(!pxFrame->IsMessageQueueEmpty()){ pxFrame->FudgeForceRedrawOfMainWindow(); } break; ... When called from the tread, the FudgeForceRedrawOfMainWindow() function never has any messages in the queue (in the PeekMessage(...) and therefore the PumpMessage() is never called. HOWEVER if I call the FudgeForceRedrawOfMainWindow()in the same thread as the MainApp ( in lengthy interations) it works fine! I´m a bit stumped about this.... bum... and I thought I´d got rid of all the bugs :(
Exactly what are you trying to do and what is the problem? You could always post a message from your worker thread to your main window (which is owned by your main thread) and do your strange IsMessageQueueEmpty() and FudgeForceRedrawOfMainWindow() thing there, but even without knowing the problem, I think your solution is questionable. Edit: I was thinking about it, and i only managed to think up one classic mistake in which this would be necessary. Immediately after creating a worker thread, you wait for the worker thread to finish in the main thread which of course means that the main thread is unable to handle messages. -- modified at 8:50 Wednesday 28th June, 2006
-
Exactly what are you trying to do and what is the problem? You could always post a message from your worker thread to your main window (which is owned by your main thread) and do your strange IsMessageQueueEmpty() and FudgeForceRedrawOfMainWindow() thing there, but even without knowing the problem, I think your solution is questionable. Edit: I was thinking about it, and i only managed to think up one classic mistake in which this would be necessary. Immediately after creating a worker thread, you wait for the worker thread to finish in the main thread which of course means that the main thread is unable to handle messages. -- modified at 8:50 Wednesday 28th June, 2006
My Problem is that I have to use CDAO* MFC classes for an application nad they are not multithreaded. Using another library / collection is not an option (boo hoo!). Opening tables and querys using the dereived tables takes (sometimes) ages. During this time, the UI does not process the normal messages (WM_DRAW etc). To get around this, I am trying to create a worker thread that will "Force" the Main window (CMainFrame) to update it´self. Some functions within the CMainFrame have an iterationary style, therefore I can call my "FudgeForceRedrawOfMainWindow()" every n steps in the iteration. Unfortuntly, the DB functions are not, for example CDaoDatabase.Execute(...); That is why I am trying to call the "FudgeForceRedrawOfMainWindow()" from a worker thread, i.e. create the worker thread before calling the function (CDaoDatabase.Execute(...)) and then closing the thread once the function returns. Trying to post a message from the worker thread to the main thread (Registerd windows message WM_USER+n) does not work as they are not processed. Until AFTER the CDao* function returns. Hope this answers your question, and that is why I cannot do it any other way, and why I have posted my problem here... Phil bum... and I thought I´d got rid of all the bugs :(
-
My Problem is that I have to use CDAO* MFC classes for an application nad they are not multithreaded. Using another library / collection is not an option (boo hoo!). Opening tables and querys using the dereived tables takes (sometimes) ages. During this time, the UI does not process the normal messages (WM_DRAW etc). To get around this, I am trying to create a worker thread that will "Force" the Main window (CMainFrame) to update it´self. Some functions within the CMainFrame have an iterationary style, therefore I can call my "FudgeForceRedrawOfMainWindow()" every n steps in the iteration. Unfortuntly, the DB functions are not, for example CDaoDatabase.Execute(...); That is why I am trying to call the "FudgeForceRedrawOfMainWindow()" from a worker thread, i.e. create the worker thread before calling the function (CDaoDatabase.Execute(...)) and then closing the thread once the function returns. Trying to post a message from the worker thread to the main thread (Registerd windows message WM_USER+n) does not work as they are not processed. Until AFTER the CDao* function returns. Hope this answers your question, and that is why I cannot do it any other way, and why I have posted my problem here... Phil bum... and I thought I´d got rid of all the bugs :(
You can't get your main thread to redraw as it has to wait for CDaoDatabase.Execute(...) to return. You got the idea upside down. The worker thread is the one that should perform your lengthy processing ie. CDaoDatabase.Execute(...) should be in the worker thread and not the other way around. If you only wish to have one query execute at a time you can always disable the main window (and maybe pop up a progress bar window - one of those in which the progress just bounces left and right) before you start the thread. And re-enable the window (and kill the progress bar window) when the worker thread posts a message to the main thread that the execution has completed. -- modified at 9:03 Wednesday 28th June, 2006
-
You can't get your main thread to redraw as it has to wait for CDaoDatabase.Execute(...) to return. You got the idea upside down. The worker thread is the one that should perform your lengthy processing ie. CDaoDatabase.Execute(...) should be in the worker thread and not the other way around. If you only wish to have one query execute at a time you can always disable the main window (and maybe pop up a progress bar window - one of those in which the progress just bounces left and right) before you start the thread. And re-enable the window (and kill the progress bar window) when the worker thread posts a message to the main thread that the execution has completed. -- modified at 9:03 Wednesday 28th June, 2006
Yes I agree totally, that is how I would like to do it, but the MFC CDao classes do not allow the use with multiple threads and changing the library is not an option (even to the standard CDatabase, CRecord would be enough) As I am "only" "maintaining" this application. Only the main thread (CWinApp) can have access. It was just a thought... Thanks anyway Phil bum... and I thought I´d got rid of all the bugs :(
-
Yes I agree totally, that is how I would like to do it, but the MFC CDao classes do not allow the use with multiple threads and changing the library is not an option (even to the standard CDatabase, CRecord would be enough) As I am "only" "maintaining" this application. Only the main thread (CWinApp) can have access. It was just a thought... Thanks anyway Phil bum... and I thought I´d got rid of all the bugs :(
Did you call AfxDaoInit()/AfxDaoTerm() in the worker thread?
-
Did you call AfxDaoInit()/AfxDaoTerm() in the worker thread?
Of course, the problem is in the non existent multi-threading capabilities of the MCF DAO library. I´ll have to live with what I have and wait until I have the time to re-implement the whole DB access of the application (perhaps ADO, have to play around with that before I decide) Until then... Thanks for the time and help you have given... mfg Phil bum... and I thought I´d got rid of all the bugs :(