Solved

How to determine termination status of a thread.

Posted on 1998-10-11
11
402 Views
Last Modified: 2013-11-20
Hi

I will probably figure this out during the time period it takes someone to respond, but this weird.

So here is the setup.  I have an array of CWinThread objects.  Some of these are NULL, indicating they are not currently in use.  Others are assigned a thread that is running, but the thread will probably terminate after about, ohhhhh, 10 seconds.

To prevent the program from exiting while a thread is running, I am using this:

  int i;
  DWORD exitcode;

  for (int j = 0; j < 100; j++)
  { for (i = 0; i < 16; i++)
    { if (m_Threads[i] != NULL)
      { GetExitCodeThread (m_Threads[i]->m_hThread, &exitcode);

        if (exitcode == STILL_ACTIVE)
        { break; }
        MessageBeep (0xffffffff);
      }
    }

    if (exitcode != STILL_ACTIVE)
    { break; }

    Sleep (100); // Wait until all threads have terminated.
  }

The intent of the code is to wait until the program has exited, but the loops will never terminate early, they always go through the whole thing.

What could be causing this?
0
Comment
Question by:helpmealot
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 3
  • 3
11 Comments
 
LVL 23

Expert Comment

by:chensu
ID: 1323185
You should use the Wait functions (e.g. WaitForSingleObject) on the thread handles to detect if the threads has terminated. Your method wastes a lot of CPU time. As a result, the threads have less time to execute.
0
 
LVL 86

Accepted Solution

by:
jkr earned 70 total points
ID: 1323186
'GetExitCodeThread()' is not very reliable for this task - i prefer calling 'WaitForSingleObject()' using a small timeout - the object's state is signaled when it terminates, so 'WAIT_TIMEOUT' guarantees that it's still running...

0
 

Author Comment

by:helpmealot
ID: 1323187
Okay, it sounds like this function WaitForSingleObject is what I am looking for.  However, I am not sure how to use it.  This is my first project using threads, so I am very unclear as to what I do with it.  Can you please elaborate?  I will divide the points between you if you both give good explanations :)
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 23

Expert Comment

by:chensu
ID: 1323188
A thread object's state is signaled when the thread terminates.

if (::WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0)
{
    // the thread has terminated
}

The WaitForSingleObject function returns when one of the following occurs:

1. The specified object is in the signaled state.
2. The time-out interval elapses.
0
 
LVL 86

Expert Comment

by:jkr
ID: 1323189
Well, IMHO there's nothing to add to chensu's explanation, the only difference is that i'd use

if (::WaitForSingleObject(hThread, 1) == WAIT_TIMEOUT)
{
    // the thread is still running...
}

0
 

Author Comment

by:helpmealot
ID: 1323190
Okay I see, that seems to make sense now.  I am going to split the points between you because I was able to incorporate chensu's suggestion for the exiting part of the program and jkr's solution for the parts of the program where a new thread would start.  First though, I have one other question (coming):
0
 

Author Comment

by:helpmealot
ID: 1323191
You see, to keep track of the threads running in the program, I have created an array of CWinThreads.  When a new thread is created, this code is executed:

  { CWinThread *nThread;
    // ...
    // nthread is assigned a valid CWinThread object.

    for (int i = 0; i < 16; i++) // 16 cause I have 16 CWinThreads in the array.
    { if (m_Threads[i] != NULL)  // All CWinThreads are initialized to 0 when the program starts.
      { if (::WaitForSingleObject (m_Threads[i], 1) != WAIT_TIMEOUT) // thread is dead.
        { m_Threads[i] = nThread;
          break;
        }
      }
      else // or object hasn't been used yet.
      { m_Threads[i] = nThread;
        break;
      }
    }
  }

Is that code good?  Are there any problems with it?  Any potential improvements?  That sort of thing.

One more other question along these same lines coming:
0
 

Author Comment

by:helpmealot
ID: 1323192
When my program exits, I want it to wait for all threads to terminate.  Is this right:

  for (i = 0; i < 16; i++)
  { if (m_Threads[i] != NULL)
    { ::WaitForSingleObject (m_Threads[i]->m_hThread, INFINITE); }
  }

It seems to work, but I have had experience where something seems to work but it turns out it doesn't.  That is why I am asking :-)

Does that make sense?  Any other suggestions?

I will give each of you 75 points and an A since you have both helped me a great deal!

Thanks!
0
 
LVL 23

Expert Comment

by:chensu
ID: 1323193
1. Regarding the code when a new thread is created, I think you can use
if (::WaitForSingleObject(m_Threads[i]->m_hThread, 0) == WAIT_OBJECT_0)
instead of
if (::WaitForSingleObject(m_Threads[i]->m_hThread, 1) != WAIT_TIMEOUT)

2. Regarding the code when the program exits, I think you may use a certain time instead of INFINITE in case there is something wrong. MsgWaitForMultipleObjects or MsgWaitForMultipleObjectsEx are your options too.

In addition, it is more reliable to handle the errors returned by WaitForSingleObject.
0
 
LVL 86

Expert Comment

by:jkr
ID: 1323194
If you already have an array of thread handles (e.g. you know the number) 'WaitForMultipleObjects()' will do the job well (and is more reliable & flexible than using a loop). 'MsgWaitForMultipleObjects()' also handles messages, but if you don't need to take care about messages, it provides no advantage...
0
 

Author Comment

by:helpmealot
ID: 1323195
Okay, that has cleared up everything for me.  chensu - I am going to post a question the MFC area "addressed" to you so you can get your 75 points too.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This is to be the first in a series of articles demonstrating the development of a complete windows based application using the MFC classes.  I’ll try to keep each article focused on one (or a couple) of the tasks that one may meet.   Introductio…
Introduction: Finishing the grid – keyboard support for arrow keys to manoeuvre, entering the numbers.  The PreTranslateMessage function is to be used to intercept and respond to keyboard events. Continuing from the fourth article about sudoku. …
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an antispam), the admini…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question