Thread: Messaging Between Threads, Exiting Thread On Demand, Etc.

  1. #1
    Registered User
    Join Date
    Jun 2007
    Posts
    41

    Messaging Between Threads, Exiting Thread On Demand, Etc.

    Good afternoon everyone.... Just had a few questions regarding threads if someone wouldn't mind answering.

    I have a main thread (GUI Thread), which creates a secondary thread for processing. There are many times that I want the main thread to signal to the secondary thread to stop and exit immediately. Currently I'm using a global boolean to do this and in the secondary thread periodically checking and then calling ExitThread ( ). I'm really not a big fan of this and depending what part in the secondary thread that is being executed there is not a prompt exit.

    I basically want to set up a message scheme between the two threads so that the main can "PostThreadMessage(WM_EXIT_NOW)" and the secondary thread will check its message queue and then call ExitThread() from there. This would be nice as I could also communicate other things. Is this possible? Below is what I've tried, but the secondary thread never appears to receive a message.

    Code:
    This is global.
    
    HHOOK hook;
    Code:
    This is the main thread.
    
    secondaryThread = CreateThread(NULL, 0, ThreadFunction, NULL, 0, &threadID);
    
    ......
    
    PostThreadMessage(threadID, WM_USER + 5, 1, 1);
    Code:
    Secondary thread
    
    WINAPI threadFunction(...)
    {
      MSG msg;
      PeekMessage(&msg, NULL, WM_USER, WM_USER + 40, PM_NOREMOVE);
      hook = SetWindowsHookEx(WH_GETMESSAGE, &GetMsgProc, NULL, threadID);
    }
    
    LRESULT CALLBACK GetMsgProc(int code, WPARAM wParam, LPARAM lParam)
    {
      ExitThread(1);
      
      UnhookWindowsHookEx(hook);  
      return 1;
    }
    I don't know... I tried to set up a message queue in the secondary thread. Set a hook to catch all incoming messages, and then attempt to process that message, but I never get into the HOOK function.

    Any ideas? Any better approach to this problem?

    P.S. The PeekMessage() line I got from MSDN
    Create an event object, then create the thread. Use the WaitForSingleObject function to wait for the event to be set to the signaled state before calling PostThreadMessage. In the thread to which the message will be posted, call PeekMessage as shown here to force the system to create the message queue.
    PSS: Also, I am positive the secondary thread has not finished executing before the PostThreadMessage() has been sent.
    Last edited by HyperShadow; 06-08-2007 at 12:32 PM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Whilst there is no doubt that the 2nd approach will work, it's got the same problem as checking a global variable. If you don't check often enough, then there will always be a perceived delay between asking for it to stop, and it stopping.

    How about just checking the global more often?
    a) it will work as it works now, except perhaps more responsively
    b) checking a global variable will be a lot more efficient than some API call.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Jun 2007
    Posts
    41
    Yeah thats kind of what I was wondering. If I were to setup a message hook in the secondary thread wouldn't it be called as SOON as a message is posted to the thread without me ever having to manual check the message queue? Therefore I could technically EXIT immediately upon receiving the message? With the second approach I wouldn't have to place any checks to look for to see if the MessageQueue contained anything... right? Its more of a CALLBACK situation.

    For my current situation my thread functions are actually not that huge so placing these global checks works okay, but then again I have to litter them throughout my function and if I were to write a large function all these checks would be a pain in the arse... what if my thread function calls a lot of other functions that could also be called by the main thread must I really put these global thread checks in there too.. couldn't problems arise? Mostly I was just curious as a messaging scheme could be useful for so many other custom messages if I wanted to communicate something else.

    - So you think the message hook approach would be pretty slow?
    - So you think the message hook approach would work? My code isn't working as if the secondary thread has NO message queue at all.... does it have one? If it doesn't is there a way I can give a "Worker Thread" a message queue?

  4. #4
    Registered User
    Join Date
    May 2007
    Posts
    147
    I've written threaded applications for years, and I empathize.

    There really is no good general solution to your inquiry. Messages are THE SAME as checking a variable, actually - it's even more work. If your thread isn't pumping a message, it's working, and if it's working, it's not pumping a message queue.

    It boils down to this. There are GUI threads (with message pumps), and 'worker' threads without them. Even with a message pump, your application will take off on processing work and ignore the messages until it gets around to servicing the message pump. If you're thinking there's some kind of 'dual action' here - you're actually thinking of a thread within a thread, one working, one serving the message pump - your problem would thus remain.

    Some processes can simply be stopped. Most OS's have some thread termination API that just drops it, but that's not a common, generic and acceptable for all occasions.

    If your process requires a graceful, orderly shutdown for an early termination (which many do), there is no good alternative. Factually, in order to gracefully shut down a process, there are usually target points where that can be done, and other positions in the algorithm from which that makes little sense.

    One thing you can sometimes manage is to hold all of the data upon which an algorithm operates in an object who's scope survives the thread (that is, killing the thread doesn't mean this object is destroyed), such that you can schedule this object's destruction after a thread kill. This can otherwise create a means of terminating a thread and still gracefully shut down the resources (RAM, files, etc) it used.

    I envision this as creating an object that represents the process, hand this 'process object' to a thread for execution, then when execution is completed, this object is scheduled for destruction (a normal execution path). Early termination is hardly any different, except the object itself may contain useless information.

    It may still be important to avoid interrupting certain processes. There could be an occasion, for example, while manipulating a tree structure that an early termination leaves the tree in an invalid state, making destruction of the tree crash. This can be managed, but you should be aware you might be creating circumstances like this, creating odd, difficult to repeat bugs (you are, after all, contemplating the generation of a crash, in some sense, when terminating a thread).

  5. #5
    Registered User
    Join Date
    Jun 2007
    Posts
    41
    If you're thinking there's some kind of 'dual action' here - you're actually thinking of a thread within a thread, one working, one serving the message pump - your problem would thus remain.
    Indeed I was thinking of some sort of dual action... without that the message queue I was thinking of trying is indeed a wasted effort.

    And as for your comments regarding early termination (a HARD termination of sorts), such as a call to WINAPI's TerminateThread() are you saying that if my thread function does not allocate any memory inside of it that a call to TerminateThread() would result in no memory leaks? I read through MSDN, but wasn't 100% positive if there was ever a safe instance to use TerminateThread() rather than an internal ExitThread() call.

  6. #6
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    Code:
    TerminateThread( hThread , 0 );
    will instantly kill the thread. hThread is the handle you recieved when you created it. 0 is the exit code. Depending on why you are killing the thread, you might consider just :
    Code:
    SuspendThread(hThread);
    Last edited by abachler; 06-08-2007 at 02:49 PM.

  7. #7
    Registered User
    Join Date
    May 2007
    Posts
    147
    Hypershadow,

    In the simplest and well controlled context, yes, terminating a thread that has not allocated any resources (of any type) should result in a closure without memory leaks.

    However, under Windows, if you've used MFC, there may be some thread local storage used without your knowledge - it's small, but still "rude" ( ) to let that leak.

    Other frameworks may also have their own material, if you've used them.

    Only you can determine if your usage of a termination is sound in your design. It's definitely not a good common practice, so try not to get used to the concept as a generalized solution to stopping activity in a way that impatient users prefer.

    If you take control of the details, you can manage it.

  8. #8
    Malum in se abachler's Avatar
    Join Date
    Apr 2007
    Posts
    3,195
    thats why I suggested using suspendthread instead. I never use MFC personally. Its the suckiest suck that ever sucked in my opinion, did I mention that its teh suck?

    SuspendThread will stop execution, but without causing memory leaks. Depending on why he is stopping the thread, it may not be a problem. If he actually needs the thread killed to free its resources, then in any case he needs to have the thread exit gracefully, which means polling some global object.

  9. #9
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    This is actually becoming windows specific, but use of TerminateThread() is not a good idea as it leaves more problems than just memory (eg thread local storage). A lot of applications, implicitly or explicitly, make use of DLLs. And the workings of DLLs requires the application to (implicitly or explicitly) close the handle it has to each DLL. In a multithreaded application, each thread can have a distinct handle to the DLL. TerminateThread() will not close those handles to DLLs used by the target thread, leading to a resource leak.

    SuspendThread() does not actually terminate a thread. It simply puts it in a state of suspension. The thread will have to be resumed so it can run to completion (or, noting various caveats with TerminateThread()) terminated before the program can exit.

    In the end, I agree with Salem and JVene: it is better to design the code being run in your thread, so it CAN be terminated in a timely manner. This may mean checking for a global flag (or under windows, checking for some defined events, a mutex being locked, etc etc), but it still means your worker thread has to periodically do the check and exit when required to. If you have particular functions being used by your worker thread during which it does not make sense to exit, then you have a design trade-off: either you need to find a way to get past those functions quickly, or your GUI thread will have to wait for those functions to complete.

  10. #10
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Haven't read the thread throughoutly, but here is my solution for the problem

    I have 2 Events (CreateEvent) one for notifying some processing is needed
    one for the exiting

    The first thread uses SetEvent to communicate with the other
    And WaitForSingleOblect with Thread handle as a parameter - to wait for the second thread exit...

    The second thread main functon is like this (in pseudocode):
    Code:
    ... threadfunction(...)
    {
       for(;;)
       {
          WaitForMultipleObjects();
          switch()
          {
             case 0: /* do the work */
             case 1: /* exit thread */
             default: /* error processing */
          }
       }
    }
    The actual sample can be found in the msdn on the WaitForMultipleObjects (or MsgWaitForMutipleObjects is you need also process the thread message queue) function description.
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  11. #11
    Registered User
    Join Date
    Jun 2007
    Posts
    41
    Quote Originally Posted by grumpy View Post
    A lot of applications, implicitly or explicitly, make use of DLLs. And the workings of DLLs requires the application to (implicitly or explicitly) close the handle it has to each DLL. In a multithreaded application, each thread can have a distinct handle to the DLL. TerminateThread() will not close those handles to DLLs used by the target thread, leading to a resource leak.
    Sweet! Thats the info I wanted. Thanks.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 02-26-2009, 11:48 PM
  2. Terminating secondary thread from another thread
    By wssoh85 in forum C++ Programming
    Replies: 13
    Last Post: 12-19-2008, 05:14 AM
  3. Thread confusion
    By pyrolink in forum C Programming
    Replies: 0
    Last Post: 01-29-2006, 09:42 PM
  4. Block and wake up certain threads
    By Spark in forum C Programming
    Replies: 9
    Last Post: 06-01-2002, 03:39 AM
  5. Multi-Thread Programming
    By drdroid in forum C++ Programming
    Replies: 6
    Last Post: 04-04-2002, 02:53 PM