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.
  • G Offline
    G Offline
    GameProfessor
    wrote on last edited by
    #1

    hi, I need to create an UI-thread. The main task of this thread is to perform an infinite loop that do the sending/receiving data. This thread must be able to receive message from Main thread to change behaviour. I try to put the loop in CMyThread::Run() and put the PeekMessage also in the loop but it doesn't work. I don't know how to do it. int CMyThread::Run() { for (;;) { DoMyWork(); if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE )!=0) // my UI thread has no window { TranslateMessage(&msg); DispatchMessage(&msg); } } return CWinThread::Run(); }

    S 2 Replies Last reply
    0
    • G GameProfessor

      hi, I need to create an UI-thread. The main task of this thread is to perform an infinite loop that do the sending/receiving data. This thread must be able to receive message from Main thread to change behaviour. I try to put the loop in CMyThread::Run() and put the PeekMessage also in the loop but it doesn't work. I don't know how to do it. int CMyThread::Run() { for (;;) { DoMyWork(); if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE )!=0) // my UI thread has no window { TranslateMessage(&msg); DispatchMessage(&msg); } } return CWinThread::Run(); }

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

      GameProfessor wrote:

      I need to create an UI-thread. The main task of this thread is to perform an infinite loop that do the sending/receiving data.

      If the thread spends its time in an "infinite loop that do the sending/receiving data" it sounds like you're after a worker thread and not a UI thread; in which case a message pump may not be needed.

      Steve

      1 Reply Last reply
      0
      • G GameProfessor

        hi, I need to create an UI-thread. The main task of this thread is to perform an infinite loop that do the sending/receiving data. This thread must be able to receive message from Main thread to change behaviour. I try to put the loop in CMyThread::Run() and put the PeekMessage also in the loop but it doesn't work. I don't know how to do it. int CMyThread::Run() { for (;;) { DoMyWork(); if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE )!=0) // my UI thread has no window { TranslateMessage(&msg); DispatchMessage(&msg); } } return CWinThread::Run(); }

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

        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 1 Reply Last reply
        0
        • 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.

            S G 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.

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

                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
                • 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
                  #8

                  What for? It will not help.

                  Steve

                  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