Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Peeking into the message queue of another thread

Peeking into the message queue of another thread

Scheduled Pinned Locked Moved C / C++ / MFC
data-structuresjsontutorialquestion
9 Posts 3 Posters 1 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Offline
    P Offline
    Phil Benson
    wrote on last edited by
    #1

    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 :(

    Who the F*** is general failure and why is he reading my hard drive?

    S 1 Reply Last reply
    0
    • P Phil Benson

      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 :(

      S Offline
      S Offline
      Sarath C
      wrote on last edited by
      #2

      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++

      P 1 Reply Last reply
      0
      • S Sarath 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++

        P Offline
        P Offline
        Phil Benson
        wrote on last edited by
        #3

        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 :(

        Who the F*** is general failure and why is he reading my hard drive?

        J 1 Reply Last reply
        0
        • P Phil Benson

          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 :(

          J Offline
          J Offline
          Justin Tay
          wrote on last edited by
          #4

          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

          P 1 Reply Last reply
          0
          • J Justin Tay

            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

            P Offline
            P Offline
            Phil Benson
            wrote on last edited by
            #5

            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 :(

            Who the F*** is general failure and why is he reading my hard drive?

            J 1 Reply Last reply
            0
            • P Phil Benson

              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 :(

              J Offline
              J Offline
              Justin Tay
              wrote on last edited by
              #6

              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

              P 1 Reply Last reply
              0
              • J Justin Tay

                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

                P Offline
                P Offline
                Phil Benson
                wrote on last edited by
                #7

                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 :(

                Who the F*** is general failure and why is he reading my hard drive?

                J 1 Reply Last reply
                0
                • P Phil Benson

                  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 :(

                  J Offline
                  J Offline
                  Justin Tay
                  wrote on last edited by
                  #8

                  Did you call AfxDaoInit()/AfxDaoTerm() in the worker thread?

                  P 1 Reply Last reply
                  0
                  • J Justin Tay

                    Did you call AfxDaoInit()/AfxDaoTerm() in the worker thread?

                    P Offline
                    P Offline
                    Phil Benson
                    wrote on last edited by
                    #9

                    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 :(

                    Who the F*** is general failure and why is he reading my hard drive?

                    1 Reply Last reply
                    0
                    Reply
                    • Reply as topic
                    Log in to reply
                    • Oldest to Newest
                    • Newest to Oldest
                    • Most Votes


                    • Login

                    • Don't have an account? Register

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • World
                    • Users
                    • Groups