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. Thread execution on button press suggestion

Thread execution on button press suggestion

Scheduled Pinned Locked Moved C / C++ / MFC
c++helpquestion
14 Posts 5 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.
  • J J B 0

    Hi all, I am creating a dialog app that has a button. When the button is pressed, in OnButton function of the dialog's cpp it creates a thread (I am using CreateThread())that runs some task. I will have to wait for the task's completion by watching the thread's termination via WaitForSingleObject(hThread, INFINITE) there. Now, the thread 's execution may take seconds so the WaitForSingleObject() would actually block windows messages and the dialog window "freezes" during the time. I'd love to NOT have the dialog frozen but simply have the button disabled during the thread task's execution. As now I have two ways in mind: 1. Use Timer and places the thread creation process in the Timer's function instead. Disabling and re-enabling button can be directly done in the function. 2. Create a main thread that does the thread creation process. The main thread will disable and enable the button via PostMessage(). I am just wondering what an appropriate approach would be to solve this problem? Thanks in advance, Best Regards, Johnny

    R Offline
    R Offline
    Roger Stoltz
    wrote on last edited by
    #4

    J.B. wrote:

    I will have to wait for the task's completion by watching the thread's termination via WaitForSingleObject(hThread, INFINITE) there.

    Then there's really no point in having a second thread if you're still doing things in serial. The implementation misses the point of multithreading. I suggest you spawn the thread as you already do, but continue after the thread is created and don't wait for it. When the thread has finished its task it should post a message to the main thread/window to inform the main thread that it has finished. In the message handler you can then enable your button again and do whatever you have to do in order to clean up.


    "It's supposed to be hard, otherwise anybody could do it!" - selfquote
    "High speed never compensates for wrong direction!" - unknown

    D C S J 4 Replies Last reply
    0
    • R Roger Stoltz

      J.B. wrote:

      I will have to wait for the task's completion by watching the thread's termination via WaitForSingleObject(hThread, INFINITE) there.

      Then there's really no point in having a second thread if you're still doing things in serial. The implementation misses the point of multithreading. I suggest you spawn the thread as you already do, but continue after the thread is created and don't wait for it. When the thread has finished its task it should post a message to the main thread/window to inform the main thread that it has finished. In the message handler you can then enable your button again and do whatever you have to do in order to clean up.


      "It's supposed to be hard, otherwise anybody could do it!" - selfquote
      "High speed never compensates for wrong direction!" - unknown

      D Offline
      D Offline
      David Crow
      wrote on last edited by
      #5

      Roger Stoltz wrote:

      Then there's really no point in having a second thread if you're still doing things in serial. The implementation misses the point of multithreading.

      Agreed. It's amazing how many folks start doing Windows development synchronously.


      "Approved Workmen Are Not Ashamed" - 2 Timothy 2:15

      "Judge not by the eye but by the heart." - Native American Proverb

      S 1 Reply Last reply
      0
      • R Roger Stoltz

        J.B. wrote:

        I will have to wait for the task's completion by watching the thread's termination via WaitForSingleObject(hThread, INFINITE) there.

        Then there's really no point in having a second thread if you're still doing things in serial. The implementation misses the point of multithreading. I suggest you spawn the thread as you already do, but continue after the thread is created and don't wait for it. When the thread has finished its task it should post a message to the main thread/window to inform the main thread that it has finished. In the message handler you can then enable your button again and do whatever you have to do in order to clean up.


        "It's supposed to be hard, otherwise anybody could do it!" - selfquote
        "High speed never compensates for wrong direction!" - unknown

        C Offline
        C Offline
        cp9876
        wrote on last edited by
        #6

        That's what I was trying to describe - you did a better job!

        Peter "Until the invention of the computer, the machine gun was the device that enabled humans to make the most mistakes in the smallest amount of time."

        1 Reply Last reply
        0
        • J J B 0

          Hi all, I am creating a dialog app that has a button. When the button is pressed, in OnButton function of the dialog's cpp it creates a thread (I am using CreateThread())that runs some task. I will have to wait for the task's completion by watching the thread's termination via WaitForSingleObject(hThread, INFINITE) there. Now, the thread 's execution may take seconds so the WaitForSingleObject() would actually block windows messages and the dialog window "freezes" during the time. I'd love to NOT have the dialog frozen but simply have the button disabled during the thread task's execution. As now I have two ways in mind: 1. Use Timer and places the thread creation process in the Timer's function instead. Disabling and re-enabling button can be directly done in the function. 2. Create a main thread that does the thread creation process. The main thread will disable and enable the button via PostMessage(). I am just wondering what an appropriate approach would be to solve this problem? Thanks in advance, Best Regards, Johnny

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

          It sounds like you’re after the MsgWaitForMultipleObjects[^] function. On a side note, you probably should be using _beginthreadex[^]. Here’s a quote from MSDN on the CreateThread function:

          A thread in an executable that calls the C run-time library (CRT) should use the _beginthreadex and _endthreadex functions for thread management rather than CreateThread and ExitThread; this requires the use of the multi-threaded version of the CRT. If a thread created using CreateThread calls the CRT, the CRT may terminate the process in low-memory conditions.

          Steve

          1 Reply Last reply
          0
          • R Roger Stoltz

            J.B. wrote:

            I will have to wait for the task's completion by watching the thread's termination via WaitForSingleObject(hThread, INFINITE) there.

            Then there's really no point in having a second thread if you're still doing things in serial. The implementation misses the point of multithreading. I suggest you spawn the thread as you already do, but continue after the thread is created and don't wait for it. When the thread has finished its task it should post a message to the main thread/window to inform the main thread that it has finished. In the message handler you can then enable your button again and do whatever you have to do in order to clean up.


            "It's supposed to be hard, otherwise anybody could do it!" - selfquote
            "High speed never compensates for wrong direction!" - unknown

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

            Roger Stoltz wrote:

            Then there's really no point in having a second thread if you're still doing things in serial. The implementation misses the point of multithreading.

            While true to a large degree this is not always the case. For example, you may be doing a long task and want to keep the UI responsive or even if the UI is disabled you still want the application to repaint itself while the task is in progress. You could scatter message pumps throughout the long task but this is not always possible and even when it is it may not be practical.

            Steve

            R 1 Reply Last reply
            0
            • D David Crow

              Roger Stoltz wrote:

              Then there's really no point in having a second thread if you're still doing things in serial. The implementation misses the point of multithreading.

              Agreed. It's amazing how many folks start doing Windows development synchronously.


              "Approved Workmen Are Not Ashamed" - 2 Timothy 2:15

              "Judge not by the eye but by the heart." - Native American Proverb

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

              DavidCrow wrote:

              Agreed. It's amazing how many folks start doing Windows development synchronously.

              I know what you mean, and it is an issue. I don’t find is surprising however; its natural to think sequentially and if you're used to writing console applications even more so.

              Steve

              1 Reply Last reply
              0
              • R Roger Stoltz

                J.B. wrote:

                I will have to wait for the task's completion by watching the thread's termination via WaitForSingleObject(hThread, INFINITE) there.

                Then there's really no point in having a second thread if you're still doing things in serial. The implementation misses the point of multithreading. I suggest you spawn the thread as you already do, but continue after the thread is created and don't wait for it. When the thread has finished its task it should post a message to the main thread/window to inform the main thread that it has finished. In the message handler you can then enable your button again and do whatever you have to do in order to clean up.


                "It's supposed to be hard, otherwise anybody could do it!" - selfquote
                "High speed never compensates for wrong direction!" - unknown

                J Offline
                J Offline
                J B 0
                wrote on last edited by
                #10

                Thanks a lot for the suggestion Roger, I am wondering where I should close the thread's handle (CloseHandle(hThread)) if I do not check for its actual completion. Receiving the message handler's call does not mean the thread's already returned I think? Another problem is that my task may contain multiple thread creations at the same time, the window would need to know when they all terminated too, which then I will get their exit codes for processing(GetExitCodeThread) as well as retrieve a timestamp at the time. Some sort of "wait-until-all-done" is still needed for my case I think? And obviously that shouldn't be done in the main window. That's why I thought about creating a thread or a timer which creates and does my thread tasks. Thanks again, Best Regards, Johnny

                R 1 Reply Last reply
                0
                • J J B 0

                  Thanks a lot for the suggestion Roger, I am wondering where I should close the thread's handle (CloseHandle(hThread)) if I do not check for its actual completion. Receiving the message handler's call does not mean the thread's already returned I think? Another problem is that my task may contain multiple thread creations at the same time, the window would need to know when they all terminated too, which then I will get their exit codes for processing(GetExitCodeThread) as well as retrieve a timestamp at the time. Some sort of "wait-until-all-done" is still needed for my case I think? And obviously that shouldn't be done in the main window. That's why I thought about creating a thread or a timer which creates and does my thread tasks. Thanks again, Best Regards, Johnny

                  R Offline
                  R Offline
                  Roger Stoltz
                  wrote on last edited by
                  #11

                  In short, here's what you should do when the thread has finished its work: 1. Post a user defined message with ::PostMessage(...) to the main thread to inform it that the worker thread is terminating. 2. In the message handler you wait on the thread handle to know when the thread has terminated. 3. [Optional] Get the exit code of the thread with ::GetExitCodeThread(...). 4. Close the thread handle with ::CloseHandle(...). Read this[^] excellent article for more info about how to use worker threads. Regarding your problem with multiple worker threads I suggest that you post the thread ID from the worker threads with the user defined message. You should have a mapping between thread IDs and their handles. In the message handler you get the thread ID, look up the thread handle in the map and continue from #2 above. Don't forget to remove the thread ID and its handle from the map when you're done with it in the message handler.


                  "It's supposed to be hard, otherwise anybody could do it!" - selfquote
                  "High speed never compensates for wrong direction!" - unknown

                  J 1 Reply Last reply
                  0
                  • S Stephen Hewitt

                    Roger Stoltz wrote:

                    Then there's really no point in having a second thread if you're still doing things in serial. The implementation misses the point of multithreading.

                    While true to a large degree this is not always the case. For example, you may be doing a long task and want to keep the UI responsive or even if the UI is disabled you still want the application to repaint itself while the task is in progress. You could scatter message pumps throughout the long task but this is not always possible and even when it is it may not be practical.

                    Steve

                    R Offline
                    R Offline
                    Roger Stoltz
                    wrote on last edited by
                    #12

                    I admit I have used ::MsgWaitForMultipleObjects(...) in the way you're referring to a couple of times. But those cases were very specific. You can also get in trouble with re-entrancy with Chaos and Mayhem following if you're not careful. There was nothing in J.B.'s post that implied to me that this could be such a rare case, that's why I suggested the most common, straight-forward and less error prone way to do it. I also think you're missing my point Steve. I wrote that "the implementation misses the point of multithreading" referring to J.B.'s call to ::WaitForSingleObject(...) blocking the main thread during the wait. In that situation he would actually gain on doing the worker thread task in the main thread. I intentionally phrased it that way leaving the possibilities open for the rare cases you're thinking about, even though I doubt this would be one of them.


                    "It's supposed to be hard, otherwise anybody could do it!" - selfquote
                    "High speed never compensates for wrong direction!" - unknown

                    1 Reply Last reply
                    0
                    • R Roger Stoltz

                      In short, here's what you should do when the thread has finished its work: 1. Post a user defined message with ::PostMessage(...) to the main thread to inform it that the worker thread is terminating. 2. In the message handler you wait on the thread handle to know when the thread has terminated. 3. [Optional] Get the exit code of the thread with ::GetExitCodeThread(...). 4. Close the thread handle with ::CloseHandle(...). Read this[^] excellent article for more info about how to use worker threads. Regarding your problem with multiple worker threads I suggest that you post the thread ID from the worker threads with the user defined message. You should have a mapping between thread IDs and their handles. In the message handler you get the thread ID, look up the thread handle in the map and continue from #2 above. Don't forget to remove the thread ID and its handle from the map when you're done with it in the message handler.


                      "It's supposed to be hard, otherwise anybody could do it!" - selfquote
                      "High speed never compensates for wrong direction!" - unknown

                      J Offline
                      J Offline
                      J B 0
                      wrote on last edited by
                      #13

                      Thanks again Roger, for very informative reply and link. They helped greatly. Best Regards, Johnny

                      R 1 Reply Last reply
                      0
                      • J J B 0

                        Thanks again Roger, for very informative reply and link. They helped greatly. Best Regards, Johnny

                        R Offline
                        R Offline
                        Roger Stoltz
                        wrote on last edited by
                        #14

                        J.B. wrote:

                        Thanks again Roger, for very informative reply and link. They helped greatly.

                        You're most welcome Johnny. I'm pleased to hear that I was able to help you, so thanks for telling me. :)


                        "It's supposed to be hard, otherwise anybody could do it!" - selfquote
                        "High speed never compensates for wrong direction!" - unknown

                        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