dcsimg
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 3 123 LastLast
Results 1 to 15 of 35

Thread: How to terminate a thread from outside properly?

  1. #1
    Join Date
    Jul 2005
    Posts
    1,030

    How to terminate a thread from outside properly?

    Here is the code,
    Code:
    /* I normally end a thread by returning from the Thread function or calling ExitThread within the thread function. To close a thread from outside we can use wait and signal function accordingly. */
    
    class CFoo
    {
    public:
      CFoo();
      ~CFoo();
    
    private:
      HANDLE m_StopThread;
      HANDLE m_WaitThread;
    
      static UINT ThreadFunction(LPVOID pvParam);
    };
    
    CFoo::CFoo()
    {
      // Create events
      m_StopThread = CreateEvent(0, TRUE, FALSE, 0);
      m_WaitThread = CreateEvent(0, TRUE, FALSE, 0);
    
      // Start thread
      AfxBeginThread(ThreadFunction, this);
    }
    
    CFoo::~CFoo()
    {
      // Trigger thread to stop
      ::SetEvent(m_StopThread);
    
      // Wait until thread finished
      ::WaitForSingleObject(m_WaitThread, INFINITE);
    
      // Close handles
      ::CloseHandle(m_StopThread);
      ::CloseHandle(m_WaitThread);
    }
    
    UINT CFoo::ThreadFunction(LPVOID pvParam)
    {
      CFoo *pParent = static_cast<CFoo*>(pvParam);
    
      while(true)
      {
        // Check event for stop thread
        if(::WaitForSingleObject(pParent->m_StopThread, 0) == WAIT_OBJECT_0)
        {
          // Set event
          ::SetEvent(pParent->m_WaitThread);
    
          return 0;
        }
    
        // Do your processing
      }
    }
    If in main thread, we code main function like this,
    Code:
    int main()
    {
        CFoo foo;
    
        return 0;
    }
    Then we never get a chance to set the event to stop another thread to be signal. What should we do in this case? Thanks.

  2. #2
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    6,900

    Re: How to terminate a thread from outside properly?

    I'm not sure I'm understanding your question, but if you want to be able to stop the class thread from outside of the destructor just have a class function, say stopThead(), which just sets the m_StopThread event when called.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++17 Compiler: Microsoft VS2019 (16.3.9)

  3. #3
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: How to terminate a thread from outside properly?

    Quote Originally Posted by LarryChen View Post
    I normally end a thread by returning from the Thread function or calling ExitThread within the thread function.
    Do not call ExitThread(), this aborts the thread at that point, without allowing proper cleanup of thread stack based variables.
    There is only ONE proper cleanup and that is for the thread procedure to return normally.

    Using the above knowledge, terminating a thread cleanly from outside the thread is not possible other than doing whatever needs to be done for the thread to return normally. This could be anything from setting/clearing flags, events, mutexes, clearing the job queue, waiting, etc etc etc...

    You can call TerminateThread(), but that again, aborts the thread wherever it is, whatever it is doing without allowing proper cleanup of anything the thread might have allocated or locked. If you're really Lucky nothing at all happens, or maybe you just leak some memory which is "bad" but necessarily problematic. if you aren't Lucky this could freeze or crash the application, or could cause it to behave erattically.



    For all intents and purposes. ExitThread(retcode) is just a shorthand for TerminateThread( GetCurrentThread(), retcode ); So it's essentially just as bad as TeminateThread(). With some care, it might be 'safer' because at least the thread itself can decide to shoot itself in the head at a somewhat safer point in time than "just anywhere". But it's still not ideal.

    THe same is true for any kind of wrappers (like the C++ library wrapper and the MFC wrapper functions) around EditThread() an TerminateThread().

  4. #4
    Arjay's Avatar
    Arjay is online now Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,146

    Re: How to terminate a thread from outside properly?

    There is no way to 'terminate a thread properly'. Are you asking how to 'notify' a thread so it exits cleanly?

  5. #5
    Join Date
    Jul 2005
    Posts
    1,030

    Re: How to terminate a thread from outside properly?

    Quote Originally Posted by 2kaud View Post
    I'm not sure I'm understanding your question, but if you want to be able to stop the class thread from outside of the destructor just have a class function, say stopThead(), which just sets the m_StopThread event when called.
    My question is actually related to how to design the main function so that the program can switch between the thread and main thread elegantly. If you call StopThread in the main thread as you suggested, the problem is that how the main thread gets a chance to call it once a thread is executing ThreadFunction? Thanks.

  6. #6
    Arjay's Avatar
    Arjay is online now Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,146

    Re: How to terminate a thread from outside properly?

    Quote Originally Posted by LarryChen View Post
    My question is actually related to how to design the main function so that the program can switch between the thread and main thread elegantly.
    What do you mean by switching between the thread and main thread?

  7. #7
    Join Date
    Jul 2005
    Posts
    1,030

    Re: How to terminate a thread from outside properly?

    Quote Originally Posted by Arjay View Post
    What do you mean by switching between the thread and main thread?
    The main thread gets executed first and then another thread gets executed. But at this time, the stop event is non-signaled and so the main thread never gets a chance to be executed. Therefore main thread doesn't have a chance to set stop event to be signaled. The ThreadFunction for another thread(non-main thread) never returns.

  8. #8
    Arjay's Avatar
    Arjay is online now Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,146

    Re: How to terminate a thread from outside properly?

    Quote Originally Posted by LarryChen View Post
    The main thread gets executed first and then another thread gets executed. But at this time, the stop event is non-signaled and so the main thread never gets a chance to be executed. Therefore main thread doesn't have a chance to set stop event to be signaled. The ThreadFunction for another thread(non-main thread) never returns.
    Your CFoo class is flawed because it doesn't expose a public way to trigger the stop event. Also, not waiting in the main thread is a real problem (in your contrived example you need to sleep a bit in the main thread at least).

    Lastly, at least throw a temporary Sleep(10) into the while(true) loop in the thread. Your processor will thank you.

    Besides those imperfections, since you have triggered the stop event in CFoo::~CFoo(), you can just scope the class to force it to exit:

    Code:
    int main()
    {
        { // scoping block
            CFoo foo;
    
            Sleep(5000);  // let's the worker thread run for ~ 5 seconds before the CFoo instance gets destructed (which signals the thread to exit).
        }
        return 0;
    }
    Last edited by Arjay; November 24th, 2014 at 04:27 PM.

  9. #9
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    6,900

    Re: How to terminate a thread from outside properly?

    Lastly, at least throw a temporary Sleep(10) into the while(true) loop in the thread.
    Or use a time out interval of 10 in WaitForSingleObject().

    The main thread gets executed first and then another thread gets executed. But at this time, the stop event is non-signaled and so the main thread never gets a chance to be executed.
    Assuming the main thread does some work after foo is defined. The CFoo constructor creates the two events initially as non-signaled then the ThreadFunction thread is then started and the class constructor returns so main() processing continues with the statement after the foo definition (which in Arjay's example is sleep()). The threadfunction is started and loops checking for the stop event to be signaled and if not does its processing and loops again. When the main function terminates, the destructor of the CFoo class is called which signals the ThreadFunction to terminate and the destructor waits until it is signaled that the thread has indeed terminated itself before the destructor itself finishes.

    As long as the main() thread is running and foo is within the scope in which it was instantiated then threadFunction() will continue to run. So I'm not sure I understand when you say that the main thread never gets a chance to be executed? In your sample code in your post #1 main() terminates straight after foo is defined so the class destructor is called, threadfunction terminates gracefully and the program closes. If you want threadFunction() to keep running then the main() thread needs to keep running.

    ??
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++17 Compiler: Microsoft VS2019 (16.3.9)

  10. #10
    Join Date
    Jul 2005
    Posts
    1,030

    Re: How to terminate a thread from outside properly?

    Quote Originally Posted by Arjay View Post
    Your CFoo class is flawed because it doesn't expose a public way to trigger the stop event. Also, not waiting in the main thread is a real problem (in your contrived example you need to sleep a bit in the main thread at least).

    Lastly, at least throw a temporary Sleep(10) into the while(true) loop in the thread. Your processor will thank you.

    Besides those imperfections, since you have triggered the stop event in CFoo::~CFoo(), you can just scope the class to force it to exit:

    Code:
    int main()
    {
        { // scoping block
            CFoo foo;
    
            Sleep(5000);  // let's the worker thread run for ~ 5 seconds before the CFoo instance gets destructed (which signals the thread to exit).
        }
        return 0;
    }
    Thanks for the example. This piece of code actually is not my code. I wonder why we need a wait event here? I think a stop event is good enough to terminate a worker thread. Thanks.

  11. #11
    Join Date
    Jul 2005
    Posts
    1,030

    Re: How to terminate a thread from outside properly?

    Quote Originally Posted by 2kaud View Post
    Or use a time out interval of 10 in WaitForSingleObject().



    Assuming the main thread does some work after foo is defined. The CFoo constructor creates the two events initially as non-signaled then the ThreadFunction thread is then started and the class constructor returns so main() processing continues with the statement after the foo definition (which in Arjay's example is sleep()). The threadfunction is started and loops checking for the stop event to be signaled and if not does its processing and loops again. When the main function terminates, the destructor of the CFoo class is called which signals the ThreadFunction to terminate and the destructor waits until it is signaled that the thread has indeed terminated itself before the destructor itself finishes.

    As long as the main() thread is running and foo is within the scope in which it was instantiated then threadFunction() will continue to run. So I'm not sure I understand when you say that the main thread never gets a chance to be executed? In your sample code in your post #1 main() terminates straight after foo is defined so the class destructor is called, threadfunction terminates gracefully and the program closes. If you want threadFunction() to keep running then the main() thread needs to keep running.

    ??
    Sorry to make you confused and forget about what I said before. If the function main is like this,
    Code:
    int main()
    {
    	CFoo foo;
    	//Sleep(5000);
    
    	return 0;
    }
    It is noted that Sleep is commented out. Will worker thread be executed? Based on my debugging, it will. Why? Since main thread never calls Sleep so my understanding that worker thread is never executed. Thanks.

  12. #12
    Arjay's Avatar
    Arjay is online now Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,146

    Re: How to terminate a thread from outside properly?

    Quote Originally Posted by LarryChen View Post
    Thanks for the example. This piece of code actually is not my code. I wonder why we need a wait event here? I think a stop event is good enough to terminate a worker thread. Thanks.
    Do you understand why I added the scoping block to the main function in my code snippet? Or why I added the Sleep statement?

  13. #13
    Arjay's Avatar
    Arjay is online now Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,146

    Re: How to terminate a thread from outside properly?

    Quote Originally Posted by LarryChen View Post
    It is noted that Sleep is commented out. Will worker thread be executed? Based on my debugging, it will. Why? Since main thread never calls Sleep so my understanding that worker thread is never executed. Thanks.
    Do you realize that a thread doesn't have to sleep in order for another thread to execute?

  14. #14
    Join Date
    Jul 2005
    Posts
    1,030

    Re: How to terminate a thread from outside properly?

    Quote Originally Posted by Arjay View Post
    Do you understand why I added the scoping block to the main function in my code snippet? Or why I added the Sleep statement?
    Actually I don't understand why you added the scoping block to the main function. Would you explain it a little bit? Thanks.

  15. #15
    Join Date
    Jul 2005
    Posts
    1,030

    Re: How to terminate a thread from outside properly?

    Quote Originally Posted by Arjay View Post
    Do you realize that a thread doesn't have to sleep in order for another thread to execute?
    I realize that a thread doesn't have to sleep in order for another thread to execute based on my debugging. However, I don't understand that without calling sleep, how can one thread "yields" its execution to another thread? Thanks.

Page 1 of 3 123 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width




On-Demand Webinars (sponsored)