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. UI-thread with both message pump and an infinite loop

UI-thread with both message pump and an infinite loop

Scheduled Pinned Locked Moved C / C++ / MFC
designtutorial
14 Posts 3 Posters 0 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.
  • S Stephen Hewitt

    GameProfessor wrote:

    if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE )!=0) // my UI thread has no window { TranslateMessage(&msg); DispatchMessage(&msg); }

    This code should look like this:

    while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
    {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }

    Your code continually dispatches the same message forever since you're using the PM_NOREMOVE flag. I also use while instead of if: do some work, process all outstanding messages then repeat.

    Steve

    G Offline
    G Offline
    GameProfessor
    wrote on last edited by
    #4

    It doesn't work. I defined my message handler using ON_THREAD_MESSAG macro. And it seems that I must left the CMyThread::Run intact then these message handler can work. How can I have my thread keep on running my send/recv loop while still be able to handle message from the main thread ?

    K S 2 Replies Last reply
    0
    • G GameProfessor

      It doesn't work. I defined my message handler using ON_THREAD_MESSAG macro. And it seems that I must left the CMyThread::Run intact then these message handler can work. How can I have my thread keep on running my send/recv loop while still be able to handle message from the main thread ?

      K Offline
      K Offline
      kasturi_haribabu
      wrote on last edited by
      #5

      I think that you also introduce atleast a Sleep(0) after the DispatchMessage statement.

      G S 2 Replies Last reply
      0
      • G GameProfessor

        It doesn't work. I defined my message handler using ON_THREAD_MESSAG macro. And it seems that I must left the CMyThread::Run intact then these message handler can work. How can I have my thread keep on running my send/recv loop while still be able to handle message from the main thread ?

        S Offline
        S Offline
        Stephen Hewitt
        wrote on last edited by
        #6

        That's because by implementing your own message pump instead of using CWinThread’s you’re bypassing MFC’s message routing architecture. There are always such dangers when mixing low-level code (Win32 calls) and high-level code (MFC’s CWinThread) without understanding how they relate to each other. To do what you’re trying to do within the MFC architecture proceed as follows: 1. Override your CMyThread's OnIdle member function. It should look like this:

        BOOL CMyThread::OnIdle(LONG lCount)
        {
        DoMyWork();
        CWinThread::OnIdle(lCount);
        return TRUE;
        }

        2. Remove your CMyThread::Run override.

        Steve

        G 1 Reply Last reply
        0
        • K kasturi_haribabu

          I think that you also introduce atleast a Sleep(0) after the DispatchMessage statement.

          S Offline
          S Offline
          Stephen Hewitt
          wrote on last edited by
          #7

          What for? It will not help.

          Steve

          1 Reply Last reply
          0
          • K kasturi_haribabu

            I think that you also introduce atleast a Sleep(0) after the DispatchMessage statement.

            G Offline
            G Offline
            GameProfessor
            wrote on last edited by
            #8

            It still doesn't work. Actually, can DispatchMessage() work with a message handler defined using macro ON_THREAD_MESSAGE ?

            S 1 Reply Last reply
            0
            • G GameProfessor

              It still doesn't work. Actually, can DispatchMessage() work with a message handler defined using macro ON_THREAD_MESSAGE ?

              S Offline
              S Offline
              Stephen Hewitt
              wrote on last edited by
              #9

              I don't think so.

              Steve

              1 Reply Last reply
              0
              • S Stephen Hewitt

                That's because by implementing your own message pump instead of using CWinThread’s you’re bypassing MFC’s message routing architecture. There are always such dangers when mixing low-level code (Win32 calls) and high-level code (MFC’s CWinThread) without understanding how they relate to each other. To do what you’re trying to do within the MFC architecture proceed as follows: 1. Override your CMyThread's OnIdle member function. It should look like this:

                BOOL CMyThread::OnIdle(LONG lCount)
                {
                DoMyWork();
                CWinThread::OnIdle(lCount);
                return TRUE;
                }

                2. Remove your CMyThread::Run override.

                Steve

                G Offline
                G Offline
                GameProfessor
                wrote on last edited by
                #10

                this doesn't work because things in OnIdle() can not be a loop and the framework doesn't loop that function by itself. I need an infinite loop. I have try these two methods: Method 1: --> my thread can not handle any message from main thread BOOL CMyThread::OnIdle(LONG lCount) { for(;;) { DoMyWork(); } CWinThread::OnIdle(lCount); return TRUE; } Method 2: --> DoMyWork() only run one time after we send message from Main thread to My thread. BOOL CMyThread::OnIdle(LONG lCount) { DoMyWork(); CWinThread::OnIdle(lCount); return TRUE; } I expect DoMyWork() to be loop to run forever !!! There must be a way, isn't it?

                S 1 Reply Last reply
                0
                • G GameProfessor

                  this doesn't work because things in OnIdle() can not be a loop and the framework doesn't loop that function by itself. I need an infinite loop. I have try these two methods: Method 1: --> my thread can not handle any message from main thread BOOL CMyThread::OnIdle(LONG lCount) { for(;;) { DoMyWork(); } CWinThread::OnIdle(lCount); return TRUE; } Method 2: --> DoMyWork() only run one time after we send message from Main thread to My thread. BOOL CMyThread::OnIdle(LONG lCount) { DoMyWork(); CWinThread::OnIdle(lCount); return TRUE; } I expect DoMyWork() to be loop to run forever !!! There must be a way, isn't it?

                  S Offline
                  S Offline
                  Stephen Hewitt
                  wrote on last edited by
                  #11

                  GameProfessor wrote:

                  this doesn't work because things in OnIdle() can not be a loop

                  It will work: the loop is within MFC's CWinThread::Run function. There should be ***NO*** loop inside OnIdle! Try it and see. Remember to remove your Run override.

                  Steve

                  G 1 Reply Last reply
                  0
                  • S Stephen Hewitt

                    GameProfessor wrote:

                    this doesn't work because things in OnIdle() can not be a loop

                    It will work: the loop is within MFC's CWinThread::Run function. There should be ***NO*** loop inside OnIdle! Try it and see. Remember to remove your Run override.

                    Steve

                    G Offline
                    G Offline
                    GameProfessor
                    wrote on last edited by
                    #12

                    i'm sure it wont run because it's the first thing I've tried. !!! Here's the code: LRESULT CMyThread::OnMyMsg(WPARAM wParam, LPARAM lParam) { MessageBox(NULL,"super man","MyMSG message",MB_OK); // this never show up!!! return 0; } int CMyThread::Run() { for (;;) { i++; if (i>=10000) { i = 0; } } return CWinThread::Run(); } BOOL CMyThread::OnIdle(LONG lCount) { // TODO: Add your specialized code here and/or call the base class return CWinThread::OnIdle(lCount); }

                    S 2 Replies Last reply
                    0
                    • G GameProfessor

                      i'm sure it wont run because it's the first thing I've tried. !!! Here's the code: LRESULT CMyThread::OnMyMsg(WPARAM wParam, LPARAM lParam) { MessageBox(NULL,"super man","MyMSG message",MB_OK); // this never show up!!! return 0; } int CMyThread::Run() { for (;;) { i++; if (i>=10000) { i = 0; } } return CWinThread::Run(); } BOOL CMyThread::OnIdle(LONG lCount) { // TODO: Add your specialized code here and/or call the base class return CWinThread::OnIdle(lCount); }

                      S Offline
                      S Offline
                      Stephen Hewitt
                      wrote on last edited by
                      #13

                      I know it will; I've just build a test app from scratch and it does. So just try it ok! Here's code snippits: --------------------- // From CMyThead's implementation: BEGIN_MESSAGE_MAP(CMyThread, CWinThread) //{{AFX_MSG_MAP(CMyThread) // NOTE - the ClassWizard will add and remove mapping macros here. //}}AFX_MSG_MAP ON_THREAD_MESSAGE(WM_USER, OnFromUI) // *******IMPORTANT******* END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CMyThread message handlers BOOL CMyThread::OnIdle(LONG lCount) { DoMyWork(); // *******IMPORTANT******* CWinThread::OnIdle(lCount); // *******IMPORTANT******* return TRUE; // *******IMPORTANT******* } void CMyThread::DoMyWork() { } afx_msg LRESULT CMyThread::OnFromUI(WPARAM, LPARAM) { return 0; } // Creating the thead and a dialog: BOOL CWillWorkApp::InitInstance() { // Standard initialization // If you are not using these features and wish to reduce the size // of your final executable, you should remove from the following // the specific initialization routines you do not need. #ifdef _AFXDLL Enable3dControls(); // Call this when using MFC in a shared DLL #else Enable3dControlsStatic(); // Call this when linking to MFC statically #endif CWinThread *pThread = AfxBeginThread(RUNTIME_CLASS(CMyThread)); CWillWorkDlg dlg(pThread); m_pMainWnd = &dlg; int nResponse = dlg.DoModal(); if (nResponse == IDOK) { // TODO: Place code here to handle when the dialog is // dismissed with OK } else if (nResponse == IDCANCEL) { // TODO: Place code here to handle when the dialog is // dismissed with Cancel } // Since the dialog has been closed, return FALSE so that we exit the // application, rather than start the application's message pump. return FALSE; } // In the dialog: CWillWorkDlg::CWillWorkDlg(CWinThread *pThread, CWnd* pParent /*=NULL*/) : CDialog(CWillWorkDlg::IDD, pParent) , m_pThread(pThread) // *******IMPORTANT******* { //{{AFX_DATA_INIT(CWillWorkDlg) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CWillWorkDlg::OnButton1() { m_pThread->PostThreadMessage(WM_USER, 0, 0); // *******IMPORTANT******* } =========================== CMyThread::DoMyWork() is called continuously and CMyThread::OnFromUI is called when I press a button from a dia

                      1 Reply Last reply
                      0
                      • G GameProfessor

                        i'm sure it wont run because it's the first thing I've tried. !!! Here's the code: LRESULT CMyThread::OnMyMsg(WPARAM wParam, LPARAM lParam) { MessageBox(NULL,"super man","MyMSG message",MB_OK); // this never show up!!! return 0; } int CMyThread::Run() { for (;;) { i++; if (i>=10000) { i = 0; } } return CWinThread::Run(); } BOOL CMyThread::OnIdle(LONG lCount) { // TODO: Add your specialized code here and/or call the base class return CWinThread::OnIdle(lCount); }

                        S Offline
                        S Offline
                        Stephen Hewitt
                        wrote on last edited by
                        #14

                        The reason your code doesn't work is that you haven't removed your Run override as I instructed. MFC's message pump is in CWinThread::Run but your override (CMyThread::Run) never calls it because it enters an endless loop and the call to MFC's is after it. Remove your Run function entirely.

                        Steve

                        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